tarjan缩块,比较块中点和边的数量关系。。。
8 10 0 1 1 2 2 3 3 0 3 4 4 5 5 6 6 7 7 4 5 7 0 0
1 5
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int maxn=11000; struct Edge { int to,next; }edge[maxn*20]; int n,m,ans1,ans2; int Adj[maxn],Size; void init() { Size=0; memset(Adj,-1,sizeof(Adj)); } void Add_Edge(int u,int v) { edge[Size].to=v; edge[Size].next=Adj[u]; Adj[u]=Size++; } int Low[maxn],DFN[maxn],Stack[maxn]; bool inStack[maxn]; int Index,top; int block[maxn]; void ck() { int num=0; for(int t=1;t<=block[0];t++) { for(int i=Adj[block[t]];~i;i=edge[i].next) { int j=edge[i].to; if(inStack[j]) num++; } } num/=2; if(block[0]>num) ans1+=num; else if(block[0]<num) ans2+=num; } void tarjan(int u,int fa) { int v; Low[u]=DFN[u]=++Index; Stack[top++]=u; for(int i=Adj[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==fa) continue; if(!DFN[v]) { tarjan(v,u); Low[u]=min(Low[u],Low[v]); if(Low[v]>=DFN[u]) { memset(inStack,false,sizeof(inStack)); block[0]=0; do { block[++block[0]]=Stack[--top]; inStack[Stack[top]]=true; }while(Stack[top]!=v); block[++block[0]]=u; inStack[u]=true; ck(); } } else Low[u]=min(Low[u],DFN[v]); } } void solve() { memset(Low,0,sizeof(Low)); memset(DFN,0,sizeof(DFN)); memset(block,0,sizeof(block)); memset(inStack,0,sizeof(inStack)); top=Index=0; for(int i=0;i<n;i++) if(!DFN[i]) tarjan(i,i); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; int a,b; init(); ans1=ans2=0; for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); Add_Edge(a,b); Add_Edge(b,a); } solve(); printf("%d %d\n",ans1,ans2); } return 0; }