[kuangbin帶你飛]專題五 並查集(poj1417+dp並查集的應用)

poj1417

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

題意:

要你找出 divine 裏的所有人

思路:

  1. 由題意得邏輯關係可以得出,當是no時,x和y是不同的。(只考察no即可)
  2. 之後把可能是no時的兩個人構成一個集合
  3. 一輪輸入後,有了很多個集合。
  4. 看能不能把他們和成divine , 可輸出1.

AC

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
#define pb push_back
#define mst(x,a) memset(x,a,sizeof(x))
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
const int maxn=1000+10;
const int maxm=10000+10;
char str[100];
int f[maxn],r[maxn];
int n,m,p1,p2;
vector<int> sum[2][maxn];
int dp[maxn][maxn];
int vis[maxn];
void init()
{
    mst(dp,0);
    mst(vis,0);
    For(i,0,n)
    {
        f[i]=i;r[i]=0;
        sum[0][i].clear();
        sum[1][i].clear();
    }
    dp[0][0]=1;
}
int find(int x)
{
    if(x==f[x])return f[x];
    int root=find(f[x]);
    r[x]^=r[f[x]];
    return f[x]=root;
}
void work()
{
    For(i,1,n)
    {
        int d1=sum[0][i].size();
        int d2=sum[1][i].size();
        For(j,0,p1)
        {
            if((d1|d2)==0)
            {
                dp[i][j]=dp[i-1][j];
                //cout<<dp[i][j]<<endl;
                continue;
            }
            if(j>=d1)dp[i][j]+=dp[i-1][j-d1];
            if(j>=d2)dp[i][j]+=dp[i-1][j-d2];
        }
    }
}
void print()
{
    vector<int>ans;
    ans.clear();
    for(int i=n; i>=1; i--)
    {
        int d1=sum[0][i].size();
        int d2=sum[1][i].size();
        if((d1|d2)==0)continue;
        if(p1-d1>=0&&p2-d2>=0&&dp[i-1][p1-d1]==1)
        {
            For(k,0,d1-1)ans.pb(sum[0][i][k]);
            p1-=d1;
            p2-=d2;
        }
        else
        {
            For(k,0,d2-1)ans.pb(sum[1][i][k]);
            p1-=d2;
            p2-=d1;
        }
    }
    sort(ans.begin(),ans.end());
    int len=ans.size();
    For(i,0,len-1)printf("%d\n",ans[i]);
    printf("end\n");
}
int main()
{
    while(scanf("%d%d%d", &m,&p1,&p2)&&(m|p1|p2))
    {
        n=p1+p2;
        init();
        For(i,1,m)
        {
            int u,v;
            scanf("%d%d%s", &u,&v,str);
            int k=str[0]=='n';
            int A=find(u);
            int B=find(v);
            if(A!=B)
            {
                f[A]=B;
                r[A]=r[u]^r[v]^k;
            }
        }
        For(i,1,n)
        {
            find(i);
            sum[r[i]][f[i]].pb(i);
        }
        work();
        if(dp[n][p1]!=1)printf("no\n");
        else
            print();
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章