Description
桐桐是一个快乐的小朋友,他生活中有许多许多好玩的事,让我们一起来看看吧……
桐桐很喜欢吃棒棒糖。他家处在一大堆糖果店的附近。
但是,他们家的区域经常出现塞车、塞人等情况,这导致他不得不等到塞的车或人走光了他才能去买到他最爱吃的棒棒糖品种。于是,他去找市长帮他修路,使得每两个糖果店之间至少有两条完全不同的路。可是市长经费有限,于是让桐桐找出哪些路被塞住后会使某些糖果店与糖果店间无法到达及最少的修路条数。你能帮助他吃到他最喜爱的糖果吗?
注:1->3->2 和 1->3->4->2 为不完全不同的路,即不符合题意的路。
1->3->4->2 和 1->5->2 为完全不同的路,即符合题意的路。
Input
输入第一行是两个数n,m(n<=5000,m<=10000)
接下来的m行,每行两个数i,j,表示i,j间有一条边连接。
Output
输出有两行。第一行为塞住后就不可以到达某些糖果店的道路条数,第二行为最少的修路条数。
1 2 3 +---+---+ | | | | 6 +---+---+ 4 / 5 / / 7 +
上图是样例所表示的一个图。 下图是改变后的图,其中虚线表示应连接的边。
1 2 3 +---+---+ : | | : | | 6 +---+---+ 4 / 5 : / : / : 7 + - - - -
Sample Input
7 7 1 2 2 3 3 4 2 5 4 5 5 6 5 7
Sample Output
3 2
今天突然想复习一下tarjan
这题写的很明白,就是找环的个数,根据题目描述,判断环就行了
我写的很麻烦,dalao们写的比我好多了..
#include<cstdio> #include<iostream> #include<vector> #include<stack> #include<cstring> using namespace std; int head[5010],num[5010],low[5010],vis[5010],cstack[5010],belong[5010],in[5010],step=0,count=0; struct map { int a; int b; }; map map1[20200]; stack<int>mstack; void make(int i,int x,int y) { map1[i].a=y; map1[i].b=head[x]; head[x]=i; } bool choose(int x,int y) { if((x&1)!=0&&y==x+1) return true; if((x&1)==0&&y==x-1) return true; return false; } void tarjan(int v,int e) { int i,j,l,u; step++; num[v]=step; low[v]=step; vis[v]=1; cstack[v]=1; mstack.push(v); for(i=head[v];i;i=map1[i].b) { if(choose(i,e)==1) continue; l=map1[i].a; if(vis[l]==0) { tarjan(l,i); low[v]=min(low[v],low[l]); } else if(cstack[l]) low[v]=min(low[v],num[l]); } if(low[v]==num[v]) { count++; do { u=mstack.top(); mstack.pop(); belong[u]=count; cstack[u]=0; }while(u!=v); } } int main() { int n,m,x,y,count1=0; int i,j; scanf("%d%d",&n,&m); for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); make(i*2-1,x,y); make(i*2,y,x); } for(i=1;i<=n;i++) if(vis[i]==0) tarjan(i,-1); printf("%d\n",count-1); for(i=1;i<=n;i++) for(j=head[i];j;j=map1[j].b) if(belong[i]!=belong[map1[j].a]) in[belong[i]]++; for(i=1;i<=count;i++) if(in[i]==1) count1++; if((count1-1)/2+1==1) cout<<"0"; else printf("%d",(count1-1)/2+1); }