Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 11137 | Accepted: 4769 |
Description
Input
Output
Sample Input
7 7 1 2 2 3 3 4 2 5 4 5 5 6 5 7
Sample Output
2
Hint
1 2 3 +---+---+ | | | | 6 +---+---+ 4 / 5 / / 7 +Building new paths from 1 to 6 and from 4 to 7 satisfies the conditions.
1 2 3 +---+---+ : | | : | | 6 +---+---+ 4 / 5 : / : / : 7 + - - - -Check some of the routes:
Source
USACO 2006 January Gold
给出一个有向图G求要加几条边使得原图任意两点之间都是强连通
用tarjan缩点,求出叶子结点数,则构造图需要加(结点数+1)/2
ACcode:
#pragma warning(disable:4786)//使命名长度不受限制 #pragma comment(linker, "/STACK:102400000,102400000")//手工开栈 #include <map> #include <set> #include <queue> #include <cmath> #include <stack> #include <cctype> #include <cstdio> #include <cstring> #include <stdlib.h> #include <iostream> #include <algorithm> #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) #define rds(x) scanf("%s",x) #define rdc(x) scanf("%c",&x) #define ll long long int #define maxn 100005 #define mod 1000000007 #define INF 0x3f3f3f3f //int 最大值 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i) #define MT(x,i) memset(x,i,sizeof(x)) #define PI acos(-1.0) #define E exp(1) using namespace std; struct Edge{ int to,next; bool cut; }e[maxn]; int low[maxn],dfn[maxn],head[maxn],Stack[maxn],belong[maxn],du[maxn]; bool instack[maxn]; int tot,top,block,pos; void addedge(){ int u,v;rd2(u,v); e[tot].to=v;e[tot].next=head[u];e[tot].cut=false; head[u]=tot++; e[tot].to=u;e[tot].next=head[v];e[tot].cut=false; head[v]=tot++; } void tarjan(int u,int pre){ int v; low[u]=dfn[u]=++pos; Stack[top++]=u; instack[u]=true; for(int i=head[u];i!=-1;i=e[i].next){ v=e[i].to; if(v==pre)continue; if(!dfn[v]){ tarjan(v,u); if(low[u]>low[v])low[u]=low[v]; if(low[v]>dfn[u]) e[i].cut=e[i^1].cut=true; }else if(instack[v]&&low[u]>dfn[v]) low[u]=dfn[v]; } if(low[u]==dfn[u]){ block++; do{ v=Stack[--top]; instack[v]=false; belong[v]=block; } while(v!=u); } } void init(){ tot=top=block=pos=0; FOR(i,0,maxn-1){ head[i]=-1; Stack[i]=instack[i]=dfn[i]=du[i]=0; } } void solve(int n){ int ans(0); tarjan(1,0); for(int i=1;i<=n;++i) for(int k=head[i];k!=-1;k=e[k].next) if(e[k].cut) du[belong[i]]++; for(int i=1;i<=block;i++) if(du[i]==1) ans++; printf("%d\n",(ans+1)/2); } int main(){ int n,m; while(rd2(n,m)!=EOF){ init();FOR(i,1,m)addedge(); solve(n); } return 0; }