【传送门:BZOJ2140】
简要题意:
给出n对夫妻和他们的名字,和m对曾经互相喜欢的男女
如果第i对夫妻发生争吵,那么这对夫妻会各自找自己喜欢的男女求安慰,而被找到的男女的另一半会因为嫉妒,也去找自己喜欢的男女求安慰,如此循环
如果第i对夫妻发生争吵后,仍能组成n对男女,那么这段婚姻是不安全的,否则是安全的
判断每一对夫妻的婚姻是否安全
题解:
二分图匹配(第一眼),O(nm)的复杂度,不要你了
想其他方法,用强联通做
对于原配,女连向男,对于曾经,男连向女,然后如果第i对夫妻在同一个连通块里就说明是不安全的(可以自己想一想)
参考代码:
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> using namespace std; struct trie { int c[75],s; trie() { s=0; memset(c,-1,sizeof(c)); } }t[81000];int tot; struct node { int x,y,next; }a[31000];int len,last[8100]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } char st[9]; void bt(int d) { int len=strlen(st+1),x=0; for(int i=1;i<=len;i++) { int y; if('a'<=st[i]&&st[i]<='z') y=st[i]-'a'+1+26; else y=st[i]-'A'+1; if(t[x].c[y]==-1) t[x].c[y]=++tot; x=t[x].c[y]; } t[x].s=d; } int findid() { int len=strlen(st+1),x=0; for(int i=1;i<=len;i++) { int y; if('a'<=st[i]&&st[i]<='z') y=st[i]-'a'+1+26; else y=st[i]-'A'+1; x=t[x].c[y]; } return t[x].s; } int dfn[8100],low[8100],id; int belong[8100],s; int sta[8100],tp; bool v[8100]; void dfs(int x) { dfn[x]=low[x]=++id; sta[++tp]=x;v[x]=true; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(dfn[y]==0) { dfs(y); low[x]=min(low[x],low[y]); } else { if(v[y]==true) low[x]=min(low[x],dfn[y]); } } if(low[x]==dfn[x]) { s++;int i; do { i=sta[tp--]; belong[i]=s; v[i]=false; }while(i!=x); } } int main() { int n; scanf("%d",&n); tot=0; len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) { scanf("%s",st+1);bt(2*i-1); scanf("%s",st+1);bt(2*i); ins(2*i,2*i-1); } int m;scanf("%d",&m); for(int i=1;i<=m;i++) { int x,y; scanf("%s",st+1);x=findid(); scanf("%s",st+1);y=findid(); ins(x,y); } memset(v,false,sizeof(v)); tp=id=s=0; memset(dfn,0,sizeof(dfn)); for(int i=1;i<=2*n;i++) { if(dfn[i]==0) dfs(i); } for(int i=1;i<=n;i++) { if(belong[2*i-1]==belong[2*i]) printf("Unsafe "); else printf("Safe "); } return 0; }