Tsinsen A1320 Painting 【最大权匹配】【树形DP】
2016-05-11 14:47
477 查看
题目大意:给一棵 n 个点的树,给每条边染色为 ai(1<=ai<n)a_i (1<= a_i < n),代价为 aia_i,要求每一个点连出的边颜色不同,求最小代价及方案
考虑每棵子树对整体的影响只有它父边的颜色,可以树形DP
设F[i][j]F[i][j]表示以 i 点为根的子树,父边颜色为 j 的最小代价
但因为要求颜色不同,所以转移的过程是一个匹配问题
建图:左边是子节点,右边为颜色,权值为最小代价,即F[l][r]F[l][r]
最坏复杂度为:O(N5)O(N^5)
但题目中有叙述树为随机生成,所以期望复杂度O(跑得过)O(跑得过)
开始忘记清零 pre[S],死循环QAQ
后来记录方案的时候,边号又加错,YYY一眼看出来orz
代码辣么丑QAQ
考虑每棵子树对整体的影响只有它父边的颜色,可以树形DP
设F[i][j]F[i][j]表示以 i 点为根的子树,父边颜色为 j 的最小代价
但因为要求颜色不同,所以转移的过程是一个匹配问题
建图:左边是子节点,右边为颜色,权值为最小代价,即F[l][r]F[l][r]
最坏复杂度为:O(N5)O(N^5)
但题目中有叙述树为随机生成,所以期望复杂度O(跑得过)O(跑得过)
开始忘记清零 pre[S],死循环QAQ
后来记录方案的时候,边号又加错,YYY一眼看出来orz
代码辣么丑QAQ
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdlib> #include<cstdio> #include<ctime> #include<cmath> #define mem(x,y) memset(x,y,sizeof(x)) #define N 155 #define M 120125 #define INF 1000000000 using namespace std; int n,siz,S,T,ans=INF,t; int fa ,first[N*2],next[M],flow[M],cost[M],to[M],pre[M]; int f ,map ; int dis[N*2],p[M],d ,as ,match ; bool v[N*2]; void inser(int x,int y,int w,int c) { next[++siz]=first[x]; first[x]=siz; to[siz]=y; flow[siz]=w; cost[siz]=c; } void add_edge(int x,int y,int w,int c) { inser(x,y,w,c),inser(y,x,0,-c); } bool spfa() { mem(dis,63),mem(v,0); int head=0,tail=1,x; dis[p[1]=S]=pre[S]=0; while (head^tail) { v[x=p[++head]]=false; for (int y,i=first[x];i;i=next[i]) if (flow[i]&&dis[y=to[i]]>dis[x]+cost[i]) { dis[y]=dis[x]+cost[pre[y]=i]; if (!v[y]) v[p[++tail]=y]=true; } } return dis[0]^dis[T]; } int mcmf() { int ret=0; while (spfa()) { int w=INF; for (int i=pre[T];i;i=pre[to[i^1]]) w=min(w,flow[i]); for (int i=pre[T];i;i=pre[to[i^1]]) flow[i]-=w,flow[i^1]+=w; ret+=w*dis[T]; } return ret; } int cal(int x,int c) { int tot=0; mem(first,0),siz=1,S=d[x]+n,T=S+1; for (int i=1;i<=n;i++) if (map[x][i]&&i!=fa[x]) { add_edge(S,++tot,1,0); for (int j=1;j<n;j++) if (j^c) add_edge(tot,d[x]+j,1,f[i][j]); } for (int i=1;i<n;i++) if (i^c) add_edge(d[x]+i,T,1,0); int ret=mcmf()+c;siz=1; for (int i=1;i<=n;i++) if (map[x][i]&&i!=fa[x]) { siz+=2; for (int j=1;j<n;siz+=(j!=c)*2,j++) if (j!=c&&!flow[siz+1]) match[x][c][i]=j; } return ret; } void dfs(int x) { if (d[x]==1&&x!=1) { for (int i=1;i<n;i++) f[x][i]=i; return; } for (int i=1;i<=n;i++) if (map[x][i]&&i!=fa[x]) fa[i]=x,dfs(i); if (x^1) for (int j=1;j<n;j++) f[x][j]=cal(x,j); else f[x][0]=cal(x,0); } void DFS(int x,int c) { for (int i=1;i<=n;i++) if (match[x][c][i]) { as[map[x][i]]=match[x][c][i]; DFS(i,match[x][c][i]); } } int main() { scanf("%d",&n); for (int x,y,i=1;i<n;i++) { scanf("%d%d",&x,&y); d[x]++,d[y]++; map[x][y]=map[y][x]=i; } dfs(1); DFS(1,0); printf("%d\n",f[1][0]); for (int i=1;i<n;i++) printf("%d ",as[i]); return 0; }
相关文章推荐
- 发现大量的TIME_WAIT解决办法
- 汇编学习第四课之main函数反汇编
- ActivityViewController 使用AirDrop分享
- STM32单片机实现中断后不继续向下执行而是返回到main函数
- CDISC SDTM EC/EX domain 学习笔记 - 4
- Mac Mail中删除服务器上的邮件
- kail2.0下hping3的安装和使用
- platform-tools\adb.exe,start-server' failed -- run manually if necessary,adb启动失败,端口被占用
- How to Test Controller Concerns in Rails 4
- Contains Duplicate
- Xcode运行错误:failed to get the task for process XXX
- LNK1123: failure during conversion to COFF: file invalid or corrupt-问题解决办法
- 墙国内新建Rails应用的要点(windows 7环境, Rails 4.2.0)
- svn Error: post-commit hook failed (exit code 127) with output
- Kafka High Availability (下)
- Kafka High Availability (上)
- CDISC SDTM EC/EX domain 学习笔记 - 3
- netstat监控大量ESTABLISHED连接与Time_Wait连接问题
- http://blog.csdn.net/kufeiyun/article/details/9363621
- ORA-01035: only available to users with RESTRICTED