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;
}