poj 3177 Redundant Paths
http://poj.org/problem?id=3177
题意:给一个无向图,问至少增加多少边,使得图中的每两个点都有两条不同的路径(两条路径不能有相同的边)。
思路:很明显,在环中的点都是满足条件的。所以首先是要进行缩点,记这时的叶子数为N,然后不断的加边成环缩点就会发现最后的结果就是(N+1)/ 2.
注意处理重边和N=1的情况。

#include<set> #include<map> #include<stack> #include<queue> #include<cmath> #include<bitset> #include<string> #include<climits> #include<cstdio> #include<vector> #include<utility> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define IN puts("in") #define OUT puts("out") #define FR(x) freopen(x,"r",stdin) #define FW(x) freopen(x,"w",stdout) #define MSET(x,y) memset(x,y,sizeof(x)) #define ST system("pause") using namespace std; const int maxn = 5005; struct nd { int u,v,next; }edge[maxn*4]; int head[maxn],vis[maxn],dfn[maxn],low[maxn],belong[maxn],st[maxn],in[maxn]; int ecnt,cnt,idx,tp; void add(int u,int v) { edge[ecnt].u = u; edge[ecnt].v = v; edge[ecnt].next = head[u]; head[u] = ecnt++; } void tarjan(int pre,int u) { int i,v,flag = 1; dfn[u] = low[u] = ++idx; vis[u] = 1; st[++tp] = u; for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(v==pre&&flag){flag = 0; continue;} if(!dfn[v]){ tarjan(u,v); low[u] = min(low[v],low[u]); }else if(vis[u]) low[u] = min(dfn[v],low[u]); } if(dfn[u]==low[u]) { cnt++; do{ v = st[tp--]; vis[v] = 0; belong[v] = cnt; }while(v!=u); } } void processing() { int i,j,k,t,n,m,u,v; while(scanf("%d%d",&n,&m)==2) { MSET(vis,0); MSET(dfn,0); MSET(in,0); MSET(head,-1); ecnt = cnt = idx = tp = 0; for(i = 0; i < m; ++ i) { scanf("%d %d",&u,&v); add(u,v); add(v,u); } tarjan(-1,1); for(i = 0; i < ecnt; ++ i) { u = belong[edge[i].u]; v = belong[edge[i].v]; if(u!=v){in[v]++; in[u]++;} } k = 0; for(i = 1; i <= cnt; ++ i) if(in[i]==2)k++; if(k==1){puts("0"); continue;} printf("%d\n",(k+1)/2); } } int main() { processing(); return 0; }