1182. Team Them Up!

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;

}

  

你可能感兴趣的:(UP)