Tsinsen A1320 Painting 【最大权匹配】【树形DP】
来源:互联网 发布:电脑温度监控软件 编辑:程序博客网 时间:2024/06/05 07:51
题目大意:给一棵 n 个点的树,给每条边染色为
考虑每棵子树对整体的影响只有它父边的颜色,可以树形DP
设
但因为要求颜色不同,所以转移的过程是一个匹配问题
建图:左边是子节点,右边为颜色,权值为最小代价,即
最坏复杂度为:
但题目中有叙述树为随机生成,所以期望复杂度
开始忘记清零 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 1000000000using namespace std;int n,siz,S,T,ans=INF,t;int fa[N],first[N*2],next[M],flow[M],cost[M],to[M],pre[M];int f[N][N],map[N][N];int dis[N*2],p[M],d[N],as[N],match[N][N][N];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;}
0 0
- Tsinsen A1320 Painting 【最大权匹配】【树形DP】
- SGU 143 树形dp 求联通块的最大权
- 最大权二分匹配
- POJ3565(最大权匹配)
- HDU3395(最大权匹配)
- hdu 3722 最大权匹配
- poj 2195 最大权匹配
- poj 1192 求树的最大权子树(树形dp)
- 【HDU1520】Anniversary Party-树形DP求树的最大权值独立集
- 二分图 最佳匹配 最大权匹配
- 完备匹配下的最大权匹配
- 邦德_纪中1236_最大权匹配_状压dp
- 二分图最大权匹配算法模板
- 最大权匹配KM算法的理解
- 【二分图最大权匹配---KM算法】
- 【最大权二分匹配的KM算法】
- 最大权匹配算法(km)
- 二分图最大权匹配 (KM算法)
- 把流转化为字符串
- 使用tar和gzip对某文件夹内的某类型文件进行压缩与解压缩
- MySQL安装-Windows
- __attribute__((packed))详解(转载)
- git的使用
- Tsinsen A1320 Painting 【最大权匹配】【树形DP】
- css overflow:hidden为什么会失效
- SVM
- iOS中几种定时器
- C语言中exit(1)和exit(0)的区别
- java单例模式
- IO流的区别和选择
- 123
- UITextField 控制文本输入小数点和小数点后几位