poj1417
題意:
要你找出 divine 裏的所有人
思路:
- 由題意得邏輯關係可以得出,當是no時,x和y是不同的。(只考察no即可)
- 之後把可能是no時的兩個人構成一個集合
- 一輪輸入後,有了很多個集合。
- 看能不能把他們和成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;
}