King's Quest POJ - 1904 匈牙利算法的思想+tarjan缩点+染色
题目链接:https://cn.vjudge.net/problem/POJ-1904
自己一开始的想法,打算用匈牙利算法实现,找二分图的最大匹配。但是打了打发现,不太好实现。原因如下:匈牙利算法是不停的找增广路。如果这个题用匈牙利算法实现的时候,就是这个地方:
1 bool Find(int t) 2 { 3 for(int i=1; i<=m; i++) 4 { 5 if(line[t][i]&&Exit[i]==0) 6 { 7 Exit[i]=1; 8 if(net[i]==0||Find(net[i])) 9 { 10 net[i]=t; 11 return true; 12 } 13 } 14 } 15 }
,这个是找到合法的就返回,无法把所有的情况都找到,所以这个方法不行。
然后再去想tarjan算法,找缩点,也就是图上的两点都能都到达,如果是王子向喜欢的公主连线的话,连一条单向边,如果是公主喜欢的王子的话,然后再从公主连向王子一条单向边,这样,就能够在最大匹配的图上实现一个连通图的建立.
但是注意这个题有个坑点,在构成连通图的时候,有的王子不喜欢某个公主,但是在图上也有可能通过别的点联通起来,这个时候就需要特判一下了。
AC代码:
1 #include<iostream> 2 #include<stack> 3 #include<iomanip> 4 #include<algorithm> 5 #include<cmath> 6 #include<string> 7 #include<cstring> 8 #include<queue> 9 #include<vector> 10 #include<stdio.h> 11 #include<map> 12 using namespace std; 13 # define inf 0x3f3f3f3f 14 # define ll long long 15 const int N = 4000+100 ; 16 const int M = 250000+100 ; 17 struct node 18 { 19 int to; 20 int nex; 21 } edge[M]; 22 int head[M],low[N],dfn[N],istack[N]; 23 int num,ind,col,n,m; 24 stack<int>q; 25 vector<int>wakaka[N]; 26 vector<int>w1; 27 vector<int>ans[N]; 28 int Map[2010][2010]; 29 void init() 30 { 31 while(!q.empty())q.pop(); 32 memset(head,-1,sizeof(head)); 33 num=0,ind=0,col=0; 34 memset(low,0,sizeof(low)); 35 memset(dfn,0,sizeof(dfn)); 36 memset(istack,0,sizeof(istack)); 37 } 38 void addedge(int fr,int to) 39 { 40 edge[num].to=to; 41 edge[num].nex=head[fr]; 42 head[fr]=num++; 43 } 44 void tarjan(int u,int root) 45 { 46 q.push(u); 47 low[u]=dfn[u]=++ind; 48 for(int i=head[u]; i!=-1; i=edge[i].nex) 49 { 50 int v=edge[i].to; 51 if(dfn[v]==0) 52 { 53 tarjan(v,u); 54 low[u]=min(low[u],low[v]); 55 } 56 else if(istack[v]==0) 57 { 58 low[u]=min(low[u],dfn[v]); 59 } 60 } 61 if(low[u]==dfn[u]) 62 { 63 int t; 64 col++; 65 do 66 { 67 t=q.top(); 68 q.pop(); 69 istack[t]=col; 70 wakaka[col].push_back(t); 71 } 72 while(t!=u); 73 } 74 } 75 int main() 76 { 77 init(); 78 scanf("%d",&n); 79 int t; 80 for(int i=1; i<=n; i++) 81 { 82 scanf("%d",&m); 83 for(int j=1; j<=m; j++) 84 { 85 scanf("%d",&t); 86 addedge(i,t+n); 87 Map[i][t]=1; 88 } 89 } 90 for(int i=1; i<=n; i++) 91 { 92 scanf("%d",&t); 93 addedge(t+n,i); 94 // Map[t][i]=1; 95 } 96 for(int i=1; i<=n; i++) 97 { 98 if(dfn[i]==0) 99 { 100 tarjan(i,1); 101 } 102 } 103 for(int i=1; i<=col; i++) 104 { 105 sort(wakaka[i].begin(),wakaka[i].end()); 106 int len=wakaka[i].size(); 107 for(int j=0; j<len; j++) 108 { 109 int u=wakaka[i][j]; 110 if(u<=n)w1.push_back(u); 111 else 112 { 113 int len2=w1.size(); 114 for(int k=0; k<len2; k++) 115 { 116 if(Map[w1[k]][u-n])//判断是不是有相互喜欢的关系 117 ans[w1[k]].push_back(u-n); 118 } 119 } 120 } 121 w1.clear(); 122 } 123 for(int i=1; i<=n; i++) 124 { 125 sort(ans[i].begin(),ans[i].end()); 126 int len=ans[i].size(); 127 printf("%d",len); 128 for(int j=0; j<len; j++) 129 { 130 printf(" %d",ans[i][j]); 131 } 132 printf("\n"); 133 } 134 return 0; 135 }