分析:我们对于那些相互不憎恨的人连边,将每次参加会议的所有人(不一定是全部人,只需人数>=3且为奇数)看做一个点双联通分量,那么每个点都至少有两个点与他相邻。即需要保证双联通分量中存在奇圈。至于如何判奇圈,这里有一个性质:一个图是二分图当且仅当图中不存在奇圈。至于如何判断一个图是否是二分图,可以采用交替染色的方式判断。
传送门:FZU 2181 快来买肉松饼
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; #define MAXN 1005 struct Edge{ int v,next; }edge[MAXN*MAXN*2]; int n,m,NE,ans; int head[MAXN]; bool hate[MAXN][MAXN]; void Insert(int u,int v) { NE++; edge[NE].v=v; edge[NE].next=head[u]; head[u]=NE; } void Build() { int a,b; memset(hate,false,sizeof(hate)); while(m--){ scanf("%d%d",&a,&b); hate[a][b]=hate[b][a]=true; } for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ if(!hate[i][j]){ Insert(i,j); Insert(j,i); } } } } int cnt,_count; int low[MAXN],dfn[MAXN]; int block[MAXN]; int color[MAXN]; bool mark[MAXN]; int num[MAXN]; bool is_expelled[MAXN]; stack<int>S; bool Judge(int u,int state) { color[u]=state; for(int i=head[u];i;i=edge[i].next){ int v=edge[i].v; if(block[v]==_count){ if(color[v]&&color[u]==color[v]) return true; if(!color[v]&&Judge(v,3-state)) return true; } } return false; } void Tarjan(int u,int father) { int flag=0; low[u]=dfn[u]=++cnt; mark[u]=true; S.push(u); for(int i=head[u];i;i=edge[i].next){ int v=edge[i].v; if(v==father&&!flag){ flag=1;continue; } if(dfn[v]==0){ Tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]){ int x,tmp=0; _count++; do{ x=S.top(); S.pop(); mark[x]=false; block[x]=_count; num[tmp++]=x; }while(x!=v);//割点u可能属于多个连通块,因此不能出栈 num[tmp++]=u; memset(color,0,sizeof(color)); if(tmp>=3&&Judge(u,1)){ while(tmp>0){ is_expelled[num[--tmp]]=false; } } } }else if(mark[v]){ low[u]=min(low[u],dfn[v]); } } } void init() { cnt=_count=0;NE=0; memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(block,0,sizeof(block)); memset(is_expelled,true,sizeof(is_expelled)); memset(mark,false,sizeof(mark)); } int main() { int T,k; scanf("%d",&T); while(T--){ // if(n==0&&m==0)break; scanf("%d%d%d",&n,&m,&k); init(); Build(); for(int i=1;i<=n;i++)if(dfn[i]==0)Tarjan(i,-1); ans=0; for(int i=1;i<=n;i++)if(!is_expelled[i])ans++; if(ans>=k)puts("Let‘s Fire!"); else puts("What a Pity."); //printf("%d\n",ans); } return 0; }
传送门:poj 2942 Knights of the Round Table
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; #define MAXN 1005 struct Edge{ int v,next; }edge[MAXN*MAXN*2]; int n,m,NE,ans; int head[MAXN]; bool hate[MAXN][MAXN]; void Insert(int u,int v) { NE++; edge[NE].v=v; edge[NE].next=head[u]; head[u]=NE; } void Build() { int a,b; memset(hate,false,sizeof(hate)); while(m--){ scanf("%d%d",&a,&b); hate[a][b]=hate[b][a]=true; } for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ if(!hate[i][j]){ Insert(i,j); Insert(j,i); } } } } int cnt,_count; int low[MAXN],dfn[MAXN]; int block[MAXN]; int color[MAXN]; bool mark[MAXN]; int num[MAXN]; bool is_expelled[MAXN]; stack<int>S; bool Judge(int u,int state) { color[u]=state; for(int i=head[u];i;i=edge[i].next){ int v=edge[i].v; if(block[v]==_count){ if(color[v]&&color[u]==color[v]) return true; if(!color[v]&&Judge(v,3-state)) return true; } } return false; } void Tarjan(int u,int father) { int flag=0; low[u]=dfn[u]=++cnt; mark[u]=true; S.push(u); for(int i=head[u];i;i=edge[i].next){ int v=edge[i].v; if(v==father&&!flag){ flag=1;continue; } if(dfn[v]==0){ Tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]){ int x,tmp=0; _count++; do{ x=S.top(); S.pop(); mark[x]=false; block[x]=_count; num[tmp++]=x; }while(x!=v);//割点u可能属于多个连通块,因此不能出栈 num[tmp++]=u; memset(color,0,sizeof(color)); if(tmp>=3&&Judge(u,1)){ while(tmp>0){ is_expelled[num[--tmp]]=false; } } } }else if(mark[v]){ low[u]=min(low[u],dfn[v]); } } } void init() { cnt=_count=0;NE=0; memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(block,0,sizeof(block)); memset(is_expelled,true,sizeof(is_expelled)); memset(mark,false,sizeof(mark)); } int main() { while(scanf("%d%d",&n,&m)>0){ if(n==0&&m==0)break; init(); Build(); for(int i=1;i<=n;i++)if(dfn[i]==0)Tarjan(i,-1); ans=0; for(int i=1;i<=n;i++)if(is_expelled[i])ans++; printf("%d\n",ans); } return 0; }
时间: 2024-10-27 11:22:36