并查集求出每个集合的与祖宗是同一类人的数量和不是同一类人的数量然后只能选其中之一或不选,然后背包并求具体选择方案
按网上题解写的….
#include<cstdio>
#include<vector>
#include<utility>
#include<cstring>
#define maxn 605
using namespace std;
int dp[maxn][maxn],fa[maxn],lin[maxn],va[maxn][2],ha[maxn],sym[maxn][maxn];
int last[maxn][maxn];
int n,p1,p2;
char s[10];
void init()
{
for(int i=0;i<=p1+p2;i++)fa[i] = i;
memset(dp,0,sizeof(dp));
memset(va,0,sizeof(va));
memset(lin,0,sizeof(lin));
memset(last,0,sizeof(last));
memset(sym,0,sizeof(sym));
}
int getFarther(int i)
{
if(i==fa[i])return i;
int pre = fa[i];
fa[i] = getFarther(fa[i]);
lin[i]^=lin[pre];
return fa[i];
}
int main()
{
while(scanf("%d%d%d",&n,&p1,&p2)!=EOF)
{
if(n==0&&p1==0&&p2==0)break;
int l = 0;
init();
while(n--)
{
int flag,a,b;
scanf("%d %d %s",&a,&b,s);
if(s[0]=='y')flag = 0;
else flag = 1;
int faa = getFarther(a),fab = getFarther(b);
if(faa!=fab)
{
fa[fab] = faa;
lin[fab] = lin[b]^flag^lin[a];
}
}
for(int i=1;i<=p1+p2;i++) if(getFarther(i)==i)ha[i] = ++l;
for(int i=1;i<=p1+p2;i++) va[ha[getFarther(i)]][lin[i]]++;
dp[0][0] = 1;
for(int i=1;i<=l;i++)
for(int j=0;j<=p1;j++)
for(int k=0;k<=1;k++)
if(j-va[i][k]>=0&&dp[i-1][j-va[i][k]])
{
dp[i][j]+=dp[i-1][j-va[i][k]];
last[i][j] = va[i][k];
}
if(dp[l][p1]!=1)printf("no\n");
else{
int pre = p1;
for(int i=l;i>=1;i--)
{
//printf("%d\n",pre);
if(!pre)break;
if(last[i][pre]==va[i][0])sym[i][0]++;
else sym[i][1]++;
pre-=last[i][pre];
}
for(int i=1;i<=p1+p2;i++)
if(sym[ha[getFarther(i)]][lin[i]])printf("%d\n",i);
printf("end\n");
}
}
return 0;
}
自己xjb搞得至今感觉对但就是过不了。。。先记录一下
#include<cstdio>
#include<vector>
#include<utility>
#include<cstring>
#define maxn 2005
using namespace std;
int dp[maxn],fa[maxn],link[maxn],va[maxn][3],ha[maxn],ha2[maxn];
pair<int,int>last[maxn];
int n,p1,p2;
char s[10];
void init()
{
for(int i=0;i<=p1+p2;i++)fa[i] = i;
memset(dp,0,sizeof(dp));
memset(va,0,sizeof(va));
memset(ha,0,sizeof(ha));
memset(ha2,0,sizeof(ha2));
memset(link,0,sizeof(link));
memset(last,0,sizeof(last));
}
int getFarther(int i)
{
if(i==fa[i])return i;
int pre = fa[i];
fa[i] = getFarther(fa[i]);
link[i]^=link[pre];
return fa[i];
}
int main()
{
while(scanf("%d%d%d",&n,&p1,&p2)!=EOF)
{
if(n==0&&p1==0&&p2==0)break;
int l = 0;
init();
while(n--)
{
int flag,a,b;
scanf("%d %d %s",&a,&b,s);
if(s[0]=='y')flag = 0;
else flag = 1;
int faa = getFarther(a),fab = getFarther(b);
if(faa!=fab)
{
fa[fab] = faa;
link[fab] = link[b]^flag^link[a];
}
}
for(int i=1;i<=p1+p2;i++) if(getFarther(i)==i) {ha[i] = ++l,ha2[l] = i;}
for(int i=1;i<=p1+p2;i++) va[ha[getFarther(i)]][link[i]]++;
dp[0] = 1;
for(int i=1;i<=l;i++)
for(int j=p1;j>=0;j--)
for(int k=0;k<=1;k++)
if(va[i][k]&&j-va[i][k]>=0&&dp[j-va[i][k]])
{
dp[j] += dp[j-va[i][k]];
if(dp[j]==1)
{
last[j].first = i;
last[j].second = k;
}
if(dp[j]>1)dp[j] = 2;
}
if(dp[p1]!=1)printf("no\n");
else{
vector<pair<int,int> >ve;
int pre = p1;
while(pre)
{
ve.push_back(make_pair(ha2[last[pre].first],last[pre].second));
pre-=va[last[pre].first][last[pre].second];
}
for(int i=1;i<=p1+p2;i++)
for(int j=0;j<ve.size();j++)
if(ve[j].first==getFarther(i)&&link[i]==ve[j].second)
{
printf("%d\n",i);
}
printf("end\n");
}
}
return 0;
}