无向图缩点,不知道为啥我写tarjan就是过不了
注意最后一定要把缩点后的大小按照从大到小开始删边
比如说你删4条,在一个环中可以另外得到3个分量,但是如果放在两个环里面分别为删两边,则总和只能得到2个分量
我的代码只能过80的点(我真的尽力了,现在晚上1.55我困得哟死)
#include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long const int maxn=1e6+5; vector<int>Q[maxn]; int n,m,k,st,cnt,sz; int a[maxn],b[maxn],S[maxn],dfn[maxn],low[maxn],stk[maxn],sum[maxn]; void dfs(int now,int fa){ dfn[now]=low[now]=++cnt; stk[++st]=now; for(int i=0;i<Q[now].size();i++){ int to=Q[now][i]; //cout<<"to="<<to<<endl; if(to==fa)continue; if(!dfn[to]){ dfs(to,now); low[now]=min(low[to],low[now]); } else low[now]=min(low[now],dfn[to]); } if(dfn[now]==low[now]){ ++sz; int cur=stk[st]; while(cur!=now){ //vis[cur]=0; S[cur]=sz;sum[sz]++; st--;cur=stk[st]; } //vis[cur]=0; st--;sum[sz]++;S[cur]=sz; } } int main(){ cin>>n>>m>>k; for(int i=1;i<=m;i++){ cin>>a[i]>>b[i]; Q[a[i]].push_back(b[i]); Q[b[i]].push_back(a[i]); } for(int i=1;i<=n;i++) if(!dfn[i])dfs(i,i); int tt=0; for(int i=1;i<=m;i++) if(S[a[i]]!=S[b[i]]) tt++; int tot=sz-tt; if(k<=tt) cout<<k+tot<<endl; else { k-=tt;int ans=sz; sort(sum+1,sum+1+sz); for(int i=sz;i>=1;i--){ if(k>=sum[i]) ans+=sum[i]-1; else { ans+=k-1;break; } k-=sum[i]; if(k<=0)break; } cout<<ans<<endl; } return 0; }
正确code:
#include <cstdio> #include <algorithm> #define MAXN 4000010 struct edge{ int to, next; } e[MAXN]; int head[MAXN], tot = 0; void add_edge(int u, int v) { tot++; e[tot].to = v, e[tot].next = head[u]; head[u] = tot; } int dis[MAXN], circle[MAXN], cnt = 0, size = 0; void dfs(int node, int fa) { dis[node] = dis[fa] + 1; for (int i = head[node]; i; i = e[i].next) { int y = e[i].to; if (y == fa) continue; if (!dis[y]) { dfs(y, node); } else if (dis[y] < dis[node] + 1) { cnt++; circle[cnt] = dis[node] - dis[y] + 1; size += circle[cnt]; } } } int main() { int n, m, k; scanf("%d %d %d", &n, &m, &k); for (int i = 1; i <= m; i++) { int u, v; scanf("%d %d", &u, &v); add_edge(u, v); add_edge(v, u); } int kuai = 0; for (int i = 1; i <= n; i++) { if (!dis[i]) { dis[i] = 1, kuai++; dfs(i, 0); } } if (m - size >= k) { printf("%d\n", kuai + k); return 0; } std::sort(circle + 1, circle + 1 + cnt); int ans = m - size + kuai; k -= m - size; for (int i = cnt; i >= 1; i--) { if (k - circle[i] >= 0) { ans += circle[i] - 1; } else { ans += k - 1; break; } k -= circle[i]; if (k <= 0) break; } printf("%d\n", ans); return 0; }