1. 程式人生 > >poj2942:Knights of the Round Table——題解

poj2942:Knights of the Round Table——題解

把他 return ostream () msl i++ top std clear

http://poj.org/problem?id=2942

所寫的tarjan練習題最難的一道。

說白了難在考得不是純tarjan。

首先我們把仇恨關系處理成非仇恨關系的圖,然後找雙連通分量,在雙連通分量裏的點滿足了任意一個人可以和兩個(或以上)的人坐一起。

那麽我們接下來要判斷奇環。

發現性質:如果一個雙連通分量有奇環,那麽其中任意一點一定在某個奇環上。

也就是說,這些人拼一拼絕對能全部開會成功,我們把他們打上成功標誌。

然後搜失敗標誌的人的個數即可。

判斷奇環的方法顯然二分圖染色。

#include<stack>
#include<cstdio>
#include<cstring>
#include
<vector> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; inline int read(){ int x=0,w=1;char ch=0; while(ch<0||ch>9){if(ch==-)w=-1;ch=getchar();} while(ch>=0&&ch<=9){x=(x<<1)+(x<<3)+ch-0;ch=getchar();}
return x*w; } const int maxn=1001; struct node{ int st; int to; int nxt; }edge[2000001]; int cnt,head[maxn]; void add(int u,int v){ cnt++; edge[cnt].st=u; edge[cnt].to=v; edge[cnt].nxt=head[u]; head[u]=cnt; return; } bool dis[maxn][maxn]; bool ok[maxn]; int color[maxn];
int dfn[maxn]; int low[maxn]; bool inslt[maxn]; int t=0; int n,m; int numslt[maxn]; stack<int>q; vector<int>slt[maxn]; int slt_cnt; void tarjan(int u,int f){ t++; dfn[u]=t; low[u]=t; for(int i=head[u];i;i=edge[i].nxt){ int v=edge[i].to; if(!dfn[v]){ q.push(i); tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]){ slt_cnt++; slt[slt_cnt].clear(); while(233){ int num=q.top(); q.pop(); if(numslt[edge[num].st]!=slt_cnt){ numslt[edge[num].st]=slt_cnt; slt[slt_cnt].push_back(edge[num].st); } if(numslt[edge[num].to]!=slt_cnt){ numslt[edge[num].to]=slt_cnt; slt[slt_cnt].push_back(edge[num].to); } if(edge[num].to==v&&edge[num].st==u)break; } } }else if(f!=v){ if(low[u]>dfn[v]){ q.push(i); low[u]=dfn[v]; } } } return; } bool draw(int u){ bool ret=0; for(int i=head[u];i;i=edge[i].nxt){ int v=edge[i].to; if(!inslt[v])continue; if(color[v]==-1){ color[v]=1-color[u]; ret|=draw(v); }else if(color[v]==color[u]){ return 1; } } return ret; } void clr(){ cnt=0;slt_cnt=0; while(!q.empty())q.pop(); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(numslt,0,sizeof(numslt)); memset(head,0,sizeof(head)); memset(dis,0,sizeof(dis)); memset(ok,0,sizeof(ok)); return; } int main(){ n=read(); m=read(); while(n||m){ clr(); for(int i=1;i<=m;i++){ int u=read(); int v=read(); dis[u][v]=dis[v][u]=1; } for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ if(!dis[i][j]){ add(i,j); add(j,i); } } } for(int i=1;i<=n;i++){ if(!dfn[i]){ tarjan(i,0); } } for(int i=1;i<=slt_cnt;i++){ memset(inslt,0,sizeof(inslt)); memset(color,-1,sizeof(color)); int u; for(int j=0;j<slt[i].size();j++){ u=slt[i][j]; inslt[u]=1; } color[u]=0; if(draw(u)){ for(int j=0;j<slt[i].size();j++){ u=slt[i][j]; ok[u]=1; } } } int ans=0; for(int i=1;i<=n;i++)if(!ok[i])ans++; printf("%d\n",ans); n=read();m=read(); } return 0; }

poj2942:Knights of the Round Table——題解