POJ 1112 Team them up
这学期第一篇博客,啊啊啊,罪过啊,O(∩_∩)O哈哈~
这个题比较复杂:图论结合了简单的DP。
直接还没办法求,需要找到反图,然后才能找到思路!
解题思路:
1.给出有向图,求出无向图,然后根据无向图求出反图
2.DFS求出各一个连通分量,并给每一个连通分量染色
3.DP求出最优状态,并记录路径
详细过程:DP为了求出所有的状态-----也就是在分完第k个连通分量之前(当然是从第1个连通分量开始分的)的所有可能的状态,当分完最后一个连通分量时,就是n个人中所能分出的所有状态!!
即f[i][j]表示未分第k个连通分量时的所有状态!则有:
if(f[i][j]==1 && f[i+cnt[k][0]][j+cnt[k][1]]==0) f[i+cnt[k][0]][j+cnt[k][1]]=1;
if(f[i][j]==1 && f[i+cnt[k][1]][j+cnt[k][0]]==0) f[i+cnt[k][1]][j+cnt[k][0]]=1;
更重要的一点是:得记录路径用pre[i][j]结构体,记录前一个的i,j;记录从前一个状态到这个状态i和j上都加了什么?即记录加的是哪个k的哪一部分(0 & 1)!
#include <iostream>
using namespace std;
const int MAXN=101;
struct Record
{
int i,j;
int id,is;
}pre[MAXN][MAXN];
int map[MAXN][MAXN],n;
int dp[MAXN][MAXN];
int cnt[MAXN][2];
int dataPtr[MAXN][2],data[MAXN],next[MAXN],ind;
//int color[MAXN];
int flag[MAXN];
void addedge(int id,int is,int u)
{
data[ind]=u;
next[ind]=dataPtr[id][is];
dataPtr[id][is]=ind;
ind++;
}
bool DFS(int v,int id,int is)
{
cnt[id][is]++;
flag[v]=is;
addedge(id,is,v);
for(int u=1;u<=n;u++)
{
if(map[v][u])
{
if(flag[u]==-1)
{
if(DFS(u,id,!is)) return true;
}
else if(flag[v]==flag[u])
return true;
}
}
return false;
}
void solve()
{
int i , j , k , l , id ;
cin>>n;
//求出反图
memset(map,0,sizeof(map));
for(i=1;i<=n;i++)
{
cin>>j;
// while(j) { map[i][j]=1; } 调试①
while(j) { map[i][j]=1; cin>>j; }
}
for(i=1;i<=n;i++)
{
for(j=1;j<i;j++)
{
if(map[i][j]==1 && map[j][i]==1)
map[i][j]=map[j][i]=0;
else map[i][j]=map[j][i]=1;
}
}
////////////
///DFS得到连通分量并染色
memset(flag,-1,sizeof(flag));
// memset(cnt,0,sizeof(cnt));
// memset(dp,0,sizeof(dp));
memset(dataPtr,-1,sizeof(dataPtr)); ind=0;
//调试②:id没有赋值
id=0;
for(i=1;i<=n;i++)
{
if(flag[i]==-1)
{
if(DFS(i,++id,0))
{
cout<<"No solution"<<endl;
return ;
}
}
}
///DP记录路径并得到结果
int num=0; dp[0][0]=1;
for(k=1;k<=id;k++)
{
for(i=0;i<=num;i++)
{
j=num-i;
if(dp[i][j]==1)
{
int nexti,nextj;
for(l=0;l<2;l++)
{
nexti=i+cnt[k][l]; nextj=j+cnt[k][!l];
if(dp[nexti][nextj]==0)
{
dp[nexti][nextj]=1;
pre[nexti][nextj].i=i;
pre[nexti][nextj].j=j;
pre[nexti][nextj].id=k;
pre[nexti][nextj].is=l;
}
}
}
}
num+=cnt[k][0]+cnt[k][1];
}
for(i=n/2,j=n-i; ;i--,j++)
{
if(dp[i][j])
{
break;
}
}
///输出结果
int ind[2]={0,0};
cnt[0][0]=i; cnt[0][1]=j;
while(i || j)
{
int id=pre[i][j].id;
int is=pre[i][j].is;
for(int l=0;l<2;l++,is=!is)
{
for(int k=dataPtr[id][is];k!=-1;k=next[k])
{
cnt[++ind[l]][l]=data[k];
}
}
int tmp=i;
i=pre[i][j].i; j=pre[tmp][j].j;
}
for(i=0;i<2;i++)
{
cout<<cnt[0][i];
for(j=1;j<=cnt[0][i];j++)
cout<<" "<<cnt[j][i];
cout<<endl;
}
}
int main()
{
freopen("input.txt","r",stdin);
solve();
return 0;
}
浙公网安备 33010602011771号