NC50425. 相框
描述
输入描述
第一行共有两个整数n和m——分别表示原有的作品的焊点和导线的数量。焊点的标号为。接下来的m行每行共有两个整数——导线两端所连接的两个焊点的标号,若不与任何焊点相连,则将这一端标号为0。
原有的作品可能不是连通的。
某些焊点可能只有一根导线与之相连,在该导线的这一端与其他导线相连之前,这些焊点不允许被烧熔。
某些焊点甚至没有任何导线与之相连,由于T君只关心导线,因此这些焊点可以不被考虑。
输出描述
只包含一个整数——表示T君需要将原有的作品改造成相框的最少步数。
示例1
输入:
6 8 1 2 1 3 3 4 1 4 4 6 5 6 4 5 1 5
输出:
4
Java(javac 1.8) 解法, 执行用时: 221ms, 内存消耗: 29236K, 提交时间: 2021-03-14 17:28:38
import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; import java.text.DecimalFormat; import java.util.*; public class Main { static class Task { public int[] tn(int a){ int f[] = new int[11]; if(a==0) { return new int[2]; } int p = 1; while(a>0){ int w = a%10; f[p++] = w; a/=10; } return Arrays.copyOf(f,p); } public int[] tt(String a){ int f[] = new int[2010]; int p = 1; for(int i=a.length()-1;i>=0;--i) { f[p++] = a.charAt(i)-'0'; } return Arrays.copyOf(f, p); } static int rt = 0; static int ch[][] ; static int fa[]; static int id[]; static int mk[]; static int ct = 1; static int cnt[]; static void insert(String s,int j,int num) { int p = 0; // root for (char c : s.toCharArray()) { int d = c - 'a'; if (ch[p][d] == 0) { ch[p][d] = ct++; } p = ch[p][d]; // mk[p]+= num; } mk[p] = 1; // id[p] = 1 << j; } static int q[] ; static int q1[] ; static void build(){ int s = 0; int e = 0; for(int i=0;i<26;++i) { if(ch[0][i]>0) { q[e++] = ch[0][i]; } } while(s<e){ int c = q[s++]; // if(id[fa[c]]>0){ // id[c] = id[fa[c]]; // } mk[c] |= mk[fa[c]]; for(int j=0;j<26;++j){ if(ch[c][j]>0){ fa[ch[c][j]] = ch[fa[c]][j]; q[e++] = ch[c][j]; }else{ ch[c][j] = ch[fa[c]][j]; } } } // for(int i=e-1;i>=0;--i){ // if(id[q[i]]!=-1){ // cnt[id[q[i]]] += mk[q[i]]; // } // mk[fa[q[i]]] += mk[q[i]]; // } } static int search(String s){ int at = 0; int cnt = 0; for(char c:s.toCharArray()){ int to = c-'a'; to = ch[at][to]; int j = to; while(j != 0) { cnt += mk[to]; j = fa[j]; } } return cnt; } int p[][];double d[];int fat[];int sz[]; int sdp[][]; void get(int i,int j,List<Integer> li){ if(sdp[i][j]==0) return; get(i,sdp[i][j],li); li.add(sdp[i][j]); get(sdp[i][j],j,li); } interface Func{ void add(int u,int v); } int root(int f){ return fat[f] = fat[f]!=f?root(fat[f]):f; } void combine(int x,int y){ int rt1 = root(x); int rt2 = root(y); if(rt1!=rt2){ fat[rt1] = rt2; } } int ct1 = 0; int to[];int ne[]; int h[]; void dfs(int rt,int pass){ if(id[rt]>0){ Func fc = (x,y)->{ to[ct1] = y; ne[ct1] = h[x]; h[x] = ct1++; }; fc.add(id[pass],id[rt]); // fc.add(id[rt],id[pass]); pass = rt; } for(int i=0;i<26;++i){ if(ch[rt][i]>0){ dfs(ch[rt][i], pass); } } } // edge number is small boolean vis[]; public boolean spfa(int s, int n, double cut) { d = new double[n]; Arrays.fill(d, -len); int cnt[] = new int[n]; ArrayDeque<Integer> qu = new ArrayDeque<>(); qu.offer(s); d[s] = 0; double tot = 0; boolean in[] = new boolean[n]; while (qu.size() > 0) { int node = qu.poll(); //tot -= d[node]; in[node] = false; vis[node] = true; for (int i = h[node]; i != -1; i = ne[i]) { int v = to[i]; double w = wt[i] - cut; if (d[node] + w > d[v]) { d[v] = d[node] + w; if (++cnt[v] > n) { return true; } if (!in[v]) { tot += d[v]; if (!qu.isEmpty() && d[v] > d[qu.peekFirst()]) { qu.offerFirst(v); } else { qu.offerLast(v); } // double x = tot / q.size(); // while (d[q.peekFirst()] < x) { // q.offerLast(q.pollFirst()); // } } } } } return false; } int wt[]; void add(int u,int v,int w){ to[ct] = v; ne[ct] = h[u]; wt[ct] = w; h[u] = ct++; } void g(int n,int m){ ct = 0; h = new int[n]; Arrays.fill(h,-1); to = new int[m]; ne = new int[m]; wt = new int[m]; } double len = 0; int b = 0; boolean fob[]; int[] lu; int tp; void dfs11(int rt){ while(h[rt]!=-1){ if(st[h[rt]]){ h[rt] = ne[h[rt]]; continue; } st[h[rt]] = true; int other = h[rt]^1; st[other] = true; int j = to[h[rt]]; int lj = wt[h[rt]]; h[rt] = ne[h[rt]]; dfs11(j); lu[tp--] = lj; } } boolean st[]; public void solve(int testNumber, InputReader in, PrintWriter out) { int n = in.nextInt(); int m = in.nextInt(); int d[]= new int[n+1]; fat = new int[n+1]; for(int j=1;j<=n;++j){ fat[j] = j; } for(int i =0;i<m;++i) { int u = in.nextInt(); int v = in.nextInt(); if(root(u)!=root(v)){ combine(u,v); } d[u]++;d[v]++; } int cnt[] = new int[n+1]; int cnt1[] = new int[n+1]; TreeSet<Integer> st = new TreeSet<>(); for(int j=0;j<=n;++j){ if(d[j]==0) continue; int mk = root(j); if(j==0){ cnt1[mk] += d[j]; st.add(mk); continue; } if(d[j]%2==0){ if(d[j]>2){ cnt[mk]++; } }else{ if(d[j]==1){ cnt1[mk]++; }else{ cnt[mk]++; cnt1[mk]++; } } st.add(mk); } int r = 0; if(st.size()==1){ int y = st.pollFirst(); r = cnt[y] + cnt1[y]/2; }else{ for(int u:st){ if(cnt1[u]>0) { r += cnt[u] + (cnt1[u]-2)/2; }else{ if(cnt[u]==0){ r++; }else { r += cnt[u]; } } } r += st.size(); } out.println(r); } // int t = in.nextInt(); // int n = in.nextInt(); // int m = in.nextInt(); // // ct = 0; // h = new int[n];Arrays.fill(h,-1); // if(t==1) { // to = new int[m * 2]; // ne = new int[m * 2]; // // fob = new boolean[m * 2]; // }else{ // to = new int[m]; // ne = new int[m]; // // } // // // int rd[] = new int[n]; // int cd[] = new int[n]; // li = new int[m]; // tp = m-1; // // int rt= 0; // // for(int i=0;i<m;++i){ // int u = in.nextInt()-1; // int v = in.nextInt()-1; // add(u,v); // if(t==1){ // add(v,u); // } // cd[u]++; // rd[v]++; // rt = u; // } // // if(t==2){ // // for(int i=0;i<n;++i){ // if(rd[i]!=cd[i]){ // out.println("NO");return; // } // } // }else{ // // for(int i=0;i<n;++i){ // if(((rd[i]+cd[i])%2)>0){ // out.println("NO");return; // } // } // // } // // // // dfs11(rt, t); // // // // if(tp!=-1){ // out.print("NO"); // return; // } // // out.println("YES"); // // for(int i=0;i<m;++i){ // out.print(li[i]+ " "); // } // int f1[][] = new int[q][3]; // // for(int i=0;i<q;++i){ // for(int j=0;j<3;++j){ // f1[i][j] = in.nextInt(); // } // } // // // int h[] = new int[n+1]; // // Arrays.fill(h,-1); // // // int ne[] = new int[p*2+q]; // int to[] = new int[p*2+q]; // int wt[] = new int[p*2+q]; // ct = 0; // Func fk = (int x,int y,int z) -> { // to[ct] = y; // ne[ct] = h[x]; // wt[ct] = z; // h[x] = ct++; // }; // // for(int i=0;i<p;++i){ // int u = f[i][0]; // int v = f[i][1]; // // // // // fk.add(u,v,f[i][2]); // fk.add(v,u,f[i][2]); // } // // for(int i=0;i<q;++i){ // int u = f1[i][0]; // int v = f1[i][1]; // // // // // fk.add(u,v,f1[i][2]); // } // int dp[] = new int[n+1]; // Arrays.fill(dp,100000000); // dp[s] = 0; // // // PriorityQueue<int[]> qu = new PriorityQueue<>(Comparator.comparingInt((x)->x[0])); // qu.add(new int[]{0,s}); // while(qu.size()>0){ // int cc[] = qu.poll(); // int cur = cc[1]; // if(cc[0]!=dp[cur]) continue; // for(int j = h[cur];j!=-1;j=ne[j]){ // int v = to[j]; // if(dp[v] > dp[cur] + wt[j]){ // dp[v] = dp[cur] + wt[j]; // qu.offer(new int[]{dp[v],v}); // } // } // } // // for(int j=1;j<=n;++j){ // if(dp[j]==100000000){ // out.println("NO PATH"); // }else{ // out.println(dp[j]); // } // } // for(int t=0;t<5;++t) { // int at = fi[t]; // dp[at][t] = 0; // PriorityQueue<int[]> q = new PriorityQueue<>(Comparator.comparingInt((x) -> x[0])); // q.offer(new int[]{0, at}); // while (q.size() > 0) { // int cur[] = q.poll(); // if (cur[0] != dp[cur[1]][t]) continue; // int i = cur[1]; // for (int j = h[i]; j != -1; j = ne[j]) { // int v = to[j]; // if (dp[i][t] + wt[j] < dp[v][t]) { // dp[v][t] = dp[i][t] + wt[j]; // q.offer(new int[]{dp[v][t], v}); // } // } // } // } // int cl[] = new int[]{0,1,2,3,4}; // int rs = Integer.MAX_VALUE; // do{ // int s= dp[1][cl[0]]; // for(int j=0;j<4;++j){ // int nxt = fi[cl[j+1]]; // s += dp[nxt][cl[j]]; // } // rs = Math.min(rs,s); // // // }while(next_perm(cl)); // // out.print(rs); boolean next_perm(int[] a){ int len = a.length; for(int i=len-2,j = 0;i>=0;--i){ if(a[i]<a[i+1]){ j = len-1; for(;a[j]<=a[i];--j); int p = a[j]; a[j] = a[i]; a[i] = p; j = i+1; for(int ed = len-1;j<ed;--ed) { p = a[ed]; a[ed] = a[j]; a[j++] = p; } return true; } } return false; } static long mul(long a, long b, long p) { long res = 0, base = a; while (b > 0) { if ((b & 1L) > 0) res = (res + base) % p; base = (base + base) % p; b >>= 1; } return res; } static long mod_pow(long k, long n, long p) { long res = 1L; long temp = k % p; while (n != 0L) { if ((n & 1L) == 1L) { res = mul(res, temp, p); } temp = mul(temp, temp, p); n = n >> 1L; } return res % p; } public static double roundD(double result, int scale) { BigDecimal bg = new BigDecimal(result).setScale(scale, RoundingMode.UP); return bg.doubleValue(); } } private static void solve() { InputStream inputStream = System.in; // InputStream inputStream = null; // try { // inputStream = new FileInputStream(new File("D:\\chrome_download\\exp.out")); // } catch (FileNotFoundException e) { // e.printStackTrace(); // } OutputStream outputStream = System.out; // OutputStream outputStream = null; // File f = new File("D:\\chrome_download\\"); // try { // f.createNewFile(); // } catch (IOException e) { // e.printStackTrace(); // } // try { // outputStream = new FileOutputStream(f); // } catch (FileNotFoundException e) { // e.printStackTrace(); // } InputReader in = new InputReader(inputStream); PrintWriter out = new PrintWriter(outputStream); Task task = new Task(); task.solve(1, in, out); out.close(); } public static void main(String[] args) { new Thread(null, () -> solve(), "1", (1 << 30)).start(); // solve(); } static class InputReader { public BufferedReader reader; public StringTokenizer tokenizer; public InputReader(InputStream stream) { reader = new BufferedReader(new InputStreamReader(stream), 32768); tokenizer = null; } public String nextLine() { String line = null; try { line = reader.readLine(); } catch (IOException e) { throw new RuntimeException(e); } return line; } public String next() { while (tokenizer == null || !tokenizer.hasMoreTokens()) { try { tokenizer = new StringTokenizer(reader.readLine()); } catch (IOException e) { throw new RuntimeException(e); } } return tokenizer.nextToken(); } public int nextInt() { return Integer.parseInt(next()); } public char nextChar() { return next().charAt(0); } public int[] nextArray(int n) { int res[] = new int[n]; for (int i = 0; i < n; ++i) { res[i] = nextInt(); } return res; } public long nextLong() { return Long.parseLong(next()); } public double nextDouble() { return Double.parseDouble(next()); } } }
C++11(clang++ 3.9) 解法, 执行用时: 29ms, 内存消耗: 2008K, 提交时间: 2020-05-30 10:45:53
#include<bits/stdc++.h> using namespace std; const int MAXN=12e4; int deg[MAXN]; int cnt1[MAXN]; int cnt2[MAXN]; int p[MAXN]; int find(int x) { return p[x]=p[x]==x?x:find(p[x]); } int main() { for(int i=0;i<MAXN;i++) p[i]=i; int n,m; cin>>n>>m; int cnt0=0; while(m--) { int u,v; cin>>u>>v; if(u==0) u=++n,cnt0++; if(v==0) v=++n,cnt0++; deg[u]++,deg[v]++; int pu=find(u),pv=find(v); if(pu!=pv) p[pu]=pv; } for(int i=0;i<=n;i++) { if(deg[i]>2) cnt1[find(i)]++; if(deg[i]%2) cnt2[find(i)]++; } int tot=0; int cnt=0; int tmpAns=0; for(int i=1;i<=n;i++) if(find(i)==i&°[i]) { cnt++; if(cnt2[i]==0) tot+=max(cnt1[i],1)+1; else tot+=cnt1[i]+cnt2[i]/2; tmpAns=cnt1[i]+cnt2[i]/2; } if(cnt==1) cout<<tmpAns<<endl; else cout<<tot<<endl; }