题意:
思路:
【问题分析】
求图的最大权不相交路径及其变种,用费用最大流解决。
【建模方法】
规则(1)
把梯形中每个位置抽象为两个点<i.a>,<i.b>,建立附加源S汇T。
1、对于每个点i从<i.a>到<i.b>连接一条容量为1,费用为点i权值的有向边。
2、从S向梯形顶层每个<i.a>连一条容量为1,费用为0的有向边。
3、从梯形底层每个<i.b>向T连一条容量为1,费用为0的有向边。
4、对于每个点i和下面的两个点j,分别连一条从<i.b>到<j.a>容量为1,费用为0的有向边。
求最大费用最大流,费用流值就是结果。
规则(2)
把梯形中每个位置看做一个点i,建立附加源S汇T。
1、从S向梯形顶层每个i连一条容量为1,费用为0的有向边。
2、从梯形底层每个i向T连一条容量为无穷大,费用为0的有向边。
3、对于每个点i和下面的两个点j,分别连一条从i到j容量为1,费用为点i权值的有向边。
求最大费用最大流,费用流值就是结果。
规则(3)
把梯形中每个位置看做一个点i,建立附加源S汇T。
1、从S向梯形顶层每个i连一条容量为1,费用为0的有向边。
2、从梯形底层每个i向T连一条容量为无穷大,费用为0的有向边。
3、对于每个点i和下面的两个点j,分别连一条从i到j容量为无穷大,费用为点i权值的有向边。
求最大费用最大流,费用流值就是结果。
【建模分析】
对于规则1,要求路径完全不相交,也就是每个点最多只能被访问了一次,所以要把点拆分,之间连接容量为1的边。因为任意一条ST之间的路径都是一个解,在拆分的点内部的边费用设为点的权值,求
最大费用最大流就是费用最大的m条路经。
对于规则2,要求路径可以相交,但不能有重叠,此时可以不必拆点了。为了保证路径没有重叠,需要在相邻的两个点上限制流量为1,由于顶层的每个点只能用1次,S向顶层点流量限制也为1。费用只需
设在相邻点的边上,求最大费用最大流即可。
对于规则3,要求路径除了顶层每个点以外可以任意相交重叠。在规则2的基础上,取消除S到顶层顶点之间的边以外所有边的流量限制即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef long double ld; 7 typedef pair<int,int> PII; 8 typedef pair<ll,ll> Pll; 9 typedef vector<int> VI; 10 typedef vector<PII> VII; 11 typedef pair<ll,ll>P; 12 #define N 100010 13 #define M 1000000 14 #define INF 1e9 15 #define fi first 16 #define se second 17 #define MP make_pair 18 #define pb push_back 19 #define pi acos(-1) 20 #define mem(a,b) memset(a,b,sizeof(a)) 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 23 #define lowbit(x) x&(-x) 24 #define Rand (rand()*(1<<16)+rand()) 25 #define id(x) ((x)<=B?(x):m-n/(x)+1) 26 #define ls p<<1 27 #define rs p<<1|1 28 29 const ll MOD=1e9+7,inv2=(MOD+1)/2; 30 double eps=1e-6; 31 int dx[4]={-1,1,0,0}; 32 int dy[4]={0,0,-1,1}; 33 34 int head[N],vet[N],len1[N],len2[N],nxt[N],dis[N],q[N],inq[N],a[50][50], 35 num[50][50][2],pre[N][2],s,S,T,tot,ans1,ans2,n,m; 36 37 38 39 int read() 40 { 41 int v=0,f=1; 42 char c=getchar(); 43 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 44 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 45 return v*f; 46 } 47 48 void add(int a,int b,int c,int d) 49 { 50 nxt[++tot]=head[a]; 51 vet[tot]=b; 52 len1[tot]=c; 53 len2[tot]=d; 54 head[a]=tot; 55 56 nxt[++tot]=head[b]; 57 vet[tot]=a; 58 len1[tot]=0; 59 len2[tot]=-d; 60 head[b]=tot; 61 } 62 63 int spfa() 64 { 65 rep(i,1,s) 66 { 67 dis[i]=-INF; 68 inq[i]=0; 69 } 70 int t=0,w=1; 71 q[1]=S; dis[S]=0; inq[S]=1; 72 while(t<w) 73 { 74 t++; int u=q[t%(s+5)]; inq[u]=0; 75 int e=head[u]; 76 while(e) 77 { 78 int v=vet[e]; 79 if(len1[e]&&dis[u]+len2[e]>dis[v]) 80 { 81 dis[v]=dis[u]+len2[e]; 82 pre[v][0]=u; 83 pre[v][1]=e; 84 if(!inq[v]) 85 { 86 w++; q[w%(s+5)]=v; inq[v]=1; 87 } 88 } 89 e=nxt[e]; 90 } 91 } 92 if(dis[T]==-INF) return 0; 93 return 1; 94 } 95 96 void mcf() 97 { 98 int k=T; 99 int t=INF; 100 while(k!=S) 101 { 102 int e=pre[k][1]; 103 t=min(t,len1[e]); 104 k=pre[k][0]; 105 } 106 ans1+=t; 107 k=T; 108 while(k!=S) 109 { 110 int e=pre[k][1]; 111 len1[e]-=t; 112 len1[e^1]+=t; 113 ans2+=t*len2[e]; 114 k=pre[k][0]; 115 } 116 } 117 118 void solve1() 119 { 120 tot=1; 121 rep(i,1,s) head[i]=0; 122 rep(i,1,m) add(S,num[1][i][0],1,0); 123 rep(i,1,n-1) 124 rep(j,1,m+i-1) 125 { 126 add(num[i][j][1],num[i+1][j][0],1,0); 127 add(num[i][j][1],num[i+1][j+1][0],1,0); 128 } 129 rep(i,1,n) 130 rep(j,1,m+i-1) add(num[i][j][0],num[i][j][1],1,a[i][j]); 131 rep(i,1,n+m-1) add(num[n][i][1],T,1,0); 132 ans1=ans2=0; 133 while(spfa()) mcf(); 134 printf("%d ",ans2); 135 } 136 137 void solve2() 138 { 139 tot=1; 140 rep(i,1,s) head[i]=0; 141 rep(i,1,m) add(S,num[1][i][0],1,0); 142 rep(i,1,n-1) 143 rep(j,1,m+i-1) 144 { 145 add(num[i][j][0],num[i+1][j][0],1,a[i][j]); 146 add(num[i][j][0],num[i+1][j+1][0],1,a[i][j]); 147 } 148 rep(i,1,n+m-1) add(num[n][i][0],T,INF,a[n][i]); 149 ans1=ans2=0; 150 while(spfa()) mcf(); 151 printf("%d ",ans2); 152 } 153 154 void solve3() 155 { 156 tot=1; 157 rep(i,1,s) head[i]=0; 158 rep(i,1,m) add(S,num[1][i][0],1,0); 159 rep(i,1,n-1) 160 rep(j,1,m+i-1) 161 { 162 add(num[i][j][0],num[i+1][j][0],INF,a[i][j]); 163 add(num[i][j][0],num[i+1][j+1][0],INF,a[i][j]); 164 } 165 rep(i,1,n+m-1) add(num[n][i][0],T,INF,a[n][i]); 166 ans1=ans2=0; 167 while(spfa()) mcf(); 168 printf("%d ",ans2); 169 } 170 171 int main() 172 { 173 //freopen("1.in","r",stdin); 174 m=read(),n=read(); 175 s=0; 176 rep(i,1,n) 177 rep(j,1,m+i-1) 178 { 179 a[i][j]=read(); 180 num[i][j][0]=++s; 181 num[i][j][1]=++s; 182 } 183 S=++s,T=++s; 184 solve1(); 185 solve2(); 186 solve3(); 187 return 0; 188 }