HDU3836 Equivalent Sets (Tarjan缩点+贪心)
题意:
给你一张有向图,问你最少加多少条边这张图强连通
思路:
缩点之后,如果不为1个点,答案为出度为0与入度为0的点的数量的最大值
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> //#include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #include<functional> #include<unordered_map> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 #define lowbit(x) ((x)&(-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 1e9+7; const int maxn = 5e4+100; const int maxm = 2e6+100; const int inf = 0x3f3f3f3f; const db pi = acos(-1.0); vector<int>g[maxn]; int f[maxn]; int color[maxn],dfn[maxn],low[maxn],stack[maxn],vis[maxn],cnt[maxn]; int in[maxn],out[maxn]; int top,n,m,sum,ans; int deep = 0; void tarjan(int u){ dfn[u]=++deep; low[u]=deep; vis[u]=1; stack[++top]=u; int sz=g[u].size(); for(int i=0;i<sz;i++){ int v=g[u][i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else{ if(vis[v]){ low[u]=min(low[u],low[v]); } } } if(dfn[u]==low[u]){ color[u]=++sum; vis[u]=0; while(stack[top]!=u){ color[stack[top]]=sum; vis[stack[top--]]=0; } top--; } return; } PI edge[maxn]; vector<int>v[maxn]; int find(int x){ return f[x]==x?x:f[x]=find(f[x]); } void dfs(int x, int fa){ if(x!=fa){ int t1 = find(x); int t2 = find(fa); f[t1]=t2; } if(v[x].size()==0&&x!=fa&&vis[x]==0){vis[x]=1;ans++;} for(int i = 0; i <(int)v[x].size(); i++){ int y = v[x][i]; dfs(y,fa); } } int main() { while(~scanf("%d %d", &n, &m)){ deep=0; top=ans=sum=0; for(int i = 1; i <= n; i++){ f[i]=i; color[i]=low[i]=dfn[i]=stack[i]=vis[i]=cnt[i]=0; g[i].clear(); v[i].clear();in[i]=out[i]=0; } for(int i = 1; i <= m; i++){ int x,y; scanf("%d %d", &x, &y); edge[i] = make_pair(x,y); g[x].pb(y); } for(int i = 1; i <= n; i++){ if(!dfn[i])tarjan(i); } /*for(int i = 1; i <= n; i++){ printf("--%d %d %d\n",i,color[i],low[i]); }*/ //suo dian for(int i = 1; i <= n; i++)vis[i]=0; for(int i = 1; i <= m; i++){ int x = edge[i].fst; int y = edge[i].sc; x = color[x]; y = color[y]; if(x!=y){ v[x].pb(y); in[y]++; out[x]++; } } int In=0; int Ou=0; for(int i = 1; i <= sum; i++){ if(in[i]==0)In++; if(out[i]==0)Ou++; } int ans = max(In,Ou); if(ans==1)ans--; printf("%d\n",ans); } return 0; } /* 4 3 1 2 2 3 4 3 4 3 1 2 2 3 3 4 8 6 1 2 1 3 1 5 3 4 3 6 6 7 6 5 1 2 2 3 3 1 3 5 1 4 2 2 1 2 2 1 3 3 1 2 2 3 1 3 7 6 1 2 2 3 1 3 4 5 4 6 4 7 4 5 1 2 1 3 1 4 2 3 3 4 4 5 1 2 1 3 1 4 2 3 4 3 3 1 1 2 */