http://acm.timus.ru/problem.aspx?space=1&num=1182
比较麻烦的一道题
先将不是相互知道的两个人重新建边 A知道B 但B不知道A 也需要建边(双向边)
新的图是m个连同块 对于每个连同块 用bfs将他们分成两组 组1 和组2 如果分的过程中出现矛盾 则无解
否则就会有m对 然后根据这m对 用DP的思想求最优解 既可
代码:
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<set> #include<map> #include<string> #include<queue> #include<stack> #include <iomanip> using namespace std; #define LL long long const int INF=0x3f3f3f3f; //priority_queue<int,vector<int>,greater<int> >qt; const int N=205; bool know[N][N]; vector<int>graph1[N]; vector<int>graph2[N]; int choose[N][N]; int head[N],I; struct node { int j,next; }side[N*N]; int in[N]; void add(int i,int j) { side[I].j=j; side[I].next=head[i]; head[i]=I++; } bool bfs(int s,int m) { in[s]=1; graph1[m].push_back(s); queue<int>qt; qt.push(s); while(!qt.empty()) { int x=qt.front(); qt.pop(); for(int t=head[x];t!=-1;t=side[t].next) { int j=side[t].j; if(in[j]==0) { if(in[x]==1) {in[j]=2;graph2[m].push_back(j);} if(in[x]==2) {in[j]=1;graph1[m].push_back(j);} qt.push(j); }else if(in[j]==in[x]) { return false; } } } return true; } int main() { //freopen("data.in","r",stdin); int n; while(cin>>n) { memset(know,false,sizeof(know)); for(int i=1;i<=n;++i) { int j; while(cin>>j) { if(!j) break; know[i][j]=true; } } memset(head,-1,sizeof(head)); I=0; for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) if(!know[i][j]||!know[j][i]) {add(i,j);add(j,i);} memset(in,0,sizeof(in)); for(int i=0;i<=n;++i) {graph1[i].clear();graph2[i].clear();} int flag=true; int m=0; for(int i=1;i<=n;++i) if(in[i]==0&&!bfs(i,m++)) {flag=false;break;} if(flag==false) {cout<<"No solution"<<endl;continue;} memset(choose,0,sizeof(choose)); stack<int>stx[2]; stack<int>sty[2]; stx[0].push(0); sty[0].push(0); int X,Y,x,y; for(int i=0;i<m;++i) { int l=i%2; int k=(i+1)%2; while(!stx[l].empty()) { x=stx[l].top();stx[l].pop(); y=sty[l].top();sty[l].pop(); X=x+graph1[i].size(); Y=y+graph2[i].size(); if(choose[X][Y]==0) {choose[X][Y]=1;stx[k].push(X);sty[k].push(Y);} X=x+graph2[i].size(); Y=y+graph1[i].size(); if(choose[X][Y]==0) {choose[X][Y]=2;stx[k].push(X);sty[k].push(Y);} } } int MAX=INF; while(!stx[m%2].empty()) { x=stx[m%2].top();stx[m%2].pop(); y=sty[m%2].top();sty[m%2].pop(); if(abs(x-y)<MAX) { MAX=abs(x-y); X=x; Y=y; } } vector<int>ans1; vector<int>ans2; while(X||Y) { --m; if(choose[X][Y]==1) { ans1.insert(ans1.end(),graph1[m].begin(),graph1[m].end()); ans2.insert(ans2.end(),graph2[m].begin(),graph2[m].end()); X=X-graph1[m].size(); Y=Y-graph2[m].size(); }else { ans2.insert(ans2.end(),graph1[m].begin(),graph1[m].end()); ans1.insert(ans1.end(),graph2[m].begin(),graph2[m].end()); X=X-graph2[m].size(); Y=Y-graph1[m].size(); } } cout<<ans1.size(); for(unsigned int i=0;i<ans1.size();++i) cout<<" "<<ans1[i]; cout<<endl; cout<<ans2.size(); for(unsigned int i=0;i<ans2.size();++i) cout<<" "<<ans2[i]; cout<<endl; } return 0; }