题意:亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突,并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有 如下要求:1:相互憎恨的两个骑士不能坐在直接相邻的2个位置;2:出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果。
现在给定准备去开会的骑士数n,再给出m对憎恨关系(表示某2个骑士之间是互相憎恨的),问有多少骑士不管跟哪些骑士都无法组成圆桌会议?
思路:没有矛盾的骑士之间建边,能组成圆桌会议的肯定形成一个环,并且环的点数为奇数。可以用Tarjan求出点双联通分量,判断每个联通分量是否存在 奇环,如果存在奇环的话,该联通分量的所有节点都可以参加会议。一个图是二分图是不存在奇环的充要条件,所以只需要判断该联通分量是否是二分图 即可。
#include<stdio.h> #include<stack> #include<math.h> #include<string.h> const int N=1010; using namespace std; int cnt[N],low[N],dfs[N],head[N],num,ans,idx,first[N],color[N],flag,n,eenum; bool map[N][N],vis[N]; struct edge { int st,ed,next; }e[N*N],ee[N*N]; void addedge(int x,int y) { e[num].st=x;e[num].ed=y;e[num].next=head[x];head[x]=num++; e[num].st=y;e[num].ed=x;e[num].next=head[y];head[y]=num++; } void Addedge(int x,int y) { ee[eenum].st=x;ee[eenum].ed=y;ee[eenum].next=first[x];first[x]=eenum++; ee[eenum].st=y;ee[eenum].ed=x;ee[eenum].next=first[y];first[y]=eenum++; } bool Judge(int u,int cor)//判断二分图 { color[u]=cor; int i,v; for(i=first[u];i!=-1;i=ee[i].next) { v=ee[i].ed; if(color[v]==-1) { return Judge(v,cor^1); } else if(color[v]==color[u])return true;//不是二分图 } return false; } stack<int>Q; void Tarjan(int u,int id) { int v,i,temp,j; dfs[u]=low[u]=idx++; for(i=head[u];i!=-1;i=e[i].next) { v=e[i].ed; if(i==(id^1))continue; if(dfs[v]==-1) { Q.push(i); Tarjan(v,i); low[u]=low[u]>low[v]?low[v]:low[u]; if(dfs[u]<=low[v])//u为割点 { memset(first,-1,sizeof(first)); memset(color,-1,sizeof(color)); eenum=0; do { temp=Q.top(); Q.pop(); Addedge(e[temp].st,e[temp].ed); }while(temp!=i);//一个双联通分量的所有边 if(Judge(u,0))//如果不是二分图该联通分量里所有点都可以参加会议 { for(j=0;j<eenum;j+=2) vis[ee[j].st]=vis[ee[j].ed]=true; } } } else if(low[u]>dfs[v]) { Q.push(i); low[u]=dfs[v]; } } } int main() { int m,x,y,i,j,sum,Case=0; while(scanf("%d%d",&n,&m)!=-1&&n+m) { memset(head,-1,sizeof(head)); memset(map,false,sizeof(map)); num=0; for(i=0;i<m;i++) { scanf("%d%d",&x,&y); map[x][y]=map[y][x]=true; } for(i=1;i<=n;i++) { for(j=i+1;j<=n;j++) if(map[i][j]==false) addedge(i,j); } memset(dfs,-1,sizeof(dfs)); memset(vis,false,sizeof(vis)); ans=idx=0;sum=0; for(i=1;i<=n;i++)//图可能不连通 { if(dfs[i]==-1) Tarjan(i,-1); } for(i=1;i<=n;i++) if(!vis[i]) sum++; printf("%d\n",sum); } return 0; }