POJ3177 & 求边双联通分量
题意:
给一张无向图,求加多少边使原图任意两点边双联通.
SOL:
一个不会写边双点双强联通的傻逼.
一个结论:把一棵树变成满足条件的图需要加的边使入度为1的点数+1除以2.------>就是树的叶子两两连上.
然后就是缩点然后统计就好了...
然后学会了怎么搞边双...看了几天白书还是非常显然的感觉...
Code:
/*========================================================================== # Last modified: 2016-03-13 17:55 # Filename: poj3177.cpp # Description: ==========================================================================*/ #define me AcrossTheSky #include <cstdio> #include <cmath> #include <ctime> #include <string> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <set> #include <map> #include <stack> #include <queue> #include <vector> #define lowbit(x) (x)&(-x) #define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++) #define FORP(i,a,b) for(int i=(a);i<=(b);i++) #define FORM(i,a,b) for(int i=(a);i>=(b);i--) #define ls(a,b) (((a)+(b)) << 1) #define rs(a,b) (((a)+(b)) >> 1) #define getlc(a) ch[(a)][0] #define getrc(a) ch[(a)][1] #define maxn 100000 #define maxm 100000 #define pi 3.1415926535898 #define _e 2.718281828459 #define INF 1070000000 using namespace std; typedef long long ll; typedef unsigned long long ull; template<class T> inline void read(T& num) { bool start=false,neg=false; char c; num=0; while((c=getchar())!=EOF) { if(c=='-') start=neg=true; else if(c>='0' && c<='9') { start=true; num=num*10+c-'0'; } else if(start) break; } if(neg) num=-num; } /*==================split line==================*/ int to[maxm],next[maxm],first[maxn]; int low[maxn],dfn[maxn],s[maxn],belong[maxn],in[maxn]; bool instack[maxn]; int sume=1,scc,clo=0,top,sum=0,n,m; void addedge(int x,int y){ sume++; to[sume]=y; next[sume]=first[x]; first[x]=sume; } void tarjan(int u,int fa){ low[u]=dfn[u]=(++clo); instack[u]=1; s[++top]=u; for (int i=first[u];i;i=next[i]){ if (i==(fa^1)) continue; int v=to[i]; if (!dfn[v]){ tarjan(v,i); low[u]=min(low[u],low[v]); } else if (instack[v]) low[u]=min(low[u],dfn[v]); } if (dfn[u]==low[u]){ scc++; while (true){ int v=s[top--]; instack[v]=false; belong[v]=scc; if (v==u) break; } } } int main(){ read(n); read(m); FORP(i,1,m){ int x,y; read(x); read(y); addedge(x,y); addedge(y,x); } FORP(i,1,n) if (!dfn[i]) tarjan(1,0); FORP(i,1,n) for (int j=first[i];j;j=next[j]) if (belong[i]!=belong[to[j]]) in[belong[i]]++; int sum=0; FORP(i,1,n) if (in[i]==1) sum++; printf("%d\n",(sum+1)/2); }
Sometimes it s the very people who no one imagines anything of. who do the things that no one can imagine.