poj 3177 Redundant Paths【縮點求出度入度】
阿新 • • 發佈:2018-12-07
題目連結:http://poj.org/problem?id=3177
題目大意:給一個無向圖,求最少新增幾條邊可以使每兩個點之間有兩條路;
思路:進行縮點後,答案為 (出度為一的點的個數+1)/2;(試了一下,出度入度都可以,因為是無向圖)
#include<cstring> #include<string> #include<cstdio> #include<stdlib.h> #include<iostream> #include<algorithm> #include<math.h> #include<map> #include<vector> #include<stack> #define inf 0x3f3f3f3f #include<queue> #include<set> using namespace std; typedef long long ll; const int N=1e5+5; const int M=1e6+5; struct node { int v,ne; }edge[M]; int head[N],dfn[N],low[N]; int vis[N];//標記是否在棧內 int belong[N];//存每個點的縮點 int m,n,top,e,cut,ans; int in[N],out[N];//存出度入度數 stack<int>sta; void add(int a,int b) { edge[e].v=b; edge[e].ne=head[a]; head[a]=e++; } void init() { while(!sta.empty()) sta.pop(); memset(head,-1,sizeof(head)); e=0; } void tarjan(int now,int pre) { low[now]=dfn[now]=++top; vis[now]=1; sta.push(now); int flag=1; for(int i=head[now];i!=-1;i=edge[i].ne) { int v=edge[i].v; if(v==pre&&flag) { flag=0; continue; } if(!dfn[v]) { tarjan(v,now); low[now]=min(low[now],low[v]); } else if(vis[v]) low[now]=min(low[now],dfn[v]); } if(low[now]==dfn[now])//縮點 { cut++; int v; while(true) { v=sta.top(); sta.pop(); belong[v]=cut; vis[v]=0; if(v==now) break; } } } void solve() { memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); top=0;cut=0;ans=0; tarjan(1,-1); for(int i=1;i<=n;i++) { for(int j=head[i];j!=-1;j=edge[j].ne) { int v=edge[j].v; if(belong[i]!=belong[v]) { in[belong[v]]++; out[belong[i]]++; } } } int res=0; for(int i=1;i<=cut;i++) { if(out[i]==1) res++; } printf("%d\n",(res+1)/2); } int main() { while(~scanf("%d %d",&n,&m)) { init(); int a,b; for(int i=0;i<m;i++) { scanf("%d %d",&a,&b); add(a,b); add(b,a); } solve(); } return 0; }