[网络流24题] 数字梯形问题 (费用流)
洛谷传送门 LOJ传送门
劳资把$spfa$里$cost$数组初始化从$-1$改成$-inf$就特么$A$了,梯形里有负数,浪费了半个多小时,心态都崩了
问题难度好像是反过来的
源点向第一排的点都流量为$1$,费用为$0$的边,最后一排的点向汇点连流量为$1$,费用为$0$的边
第三问点点之间流量$inf$,费用为指向的点的权值
第二问没啥好说的,点点之间的边流量改成$1$就行了
因为最后一排可能有很多点,所以最后一排的点向汇点的流量改成$inf$
第一问拆点
一个点不能被走$2$次,在拆开点之间连流量为$1$,费用为它权值的边
一条边不能被走$2$次,某点的出点向它能走的点的入点连流量为$1$,费用为$0$的边
然后瞎**跑最大费用最大流就行了
【暴躁!!】
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define L1 55 5 #define N1 1610 6 #define M1 40010 7 #define ll long long 8 #define dd double 9 #define inf 0x3f3f3f3f 10 using namespace std; 11 12 int gint() 13 { 14 int ret=0,fh=1;char c=getchar(); 15 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 16 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 17 return ret*fh; 18 } 19 struct Edge{ 20 int head[N1],to[M1<<1],nxt[M1<<1],flow[M1<<1],cost[M1<<1],cte; 21 void ae(int u,int v,int F,int C) 22 { 23 cte++; to[cte]=v; flow[cte]=F; cost[cte]=C; 24 nxt[cte]=head[u]; head[u]=cte; 25 } 26 }e,E; 27 int K,n,m,cnt,S,T; 28 int a[N1],que[M1<<1],hd,tl,cost[N1],flow[N1],use[N1],id[N1]; 29 int spfa() 30 { 31 int x,j,v; 32 memset(flow,0,sizeof(flow)); 33 for(j=S;j<=T;j++) 34 cost[j]=-inf; 35 hd=1,tl=0; que[++tl]=S; cost[S]=0; flow[S]=inf; use[S]=1; 36 while(hd<=tl) 37 { 38 x=que[hd++]; 39 for(j=e.head[x];j;j=e.nxt[j]) 40 { 41 v=e.to[j]; 42 if( cost[v]<cost[x]+e.cost[j] && e.flow[j]>0 ) 43 { 44 cost[v]=cost[x]+e.cost[j]; id[v]=j; 45 flow[v]=min(flow[x],e.flow[j]); 46 if(!use[v]) que[++tl]=v, use[v]=1; 47 } 48 } 49 use[x]=0; 50 } 51 return cost[T]!=-inf; 52 } 53 int EK() 54 { 55 int x,fl,tcost=0,i,j; 56 while(spfa()) 57 { 58 fl=flow[T]; tcost+=fl*cost[T]; 59 for(x=T;x!=S;x=e.to[id[x]^1]) 60 { 61 e.flow[id[x]]-=fl; 62 e.flow[id[x]^1]+=fl; 63 } 64 } 65 return tcost; 66 } 67 68 int mp[L1][L1],idd[L1][L1]; 69 int check(int x,int y){ 70 if(x<1||y<1||x>n||y>m+x-1) return 0; return 1; 71 } 72 73 namespace S1{ 74 void solve() 75 { 76 int i,j,da,db; 77 memset(&e,0,sizeof(e)); e.cte=1; 78 for(i=1;i<=n;i++) for(j=1;j<=m+i-1;j++) 79 { 80 da=idd[i][j]; 81 e.ae(da,da+cnt,1,mp[i][j]); e.ae(da+cnt,da,0,-mp[i][j]); 82 if(check(i+1,j)) { db=idd[i+1][j]; e.ae(da+cnt,db,1,0); e.ae(db,da+cnt,0,0); } 83 if(check(i+1,j+1)){ db=idd[i+1][j+1]; e.ae(da+cnt,db,1,0); e.ae(db,da+cnt,0,0); } 84 } 85 for(i=1;i<=m;i++) e.ae(S,i,1,0), e.ae(i,S,0,0); 86 for(i=1;i<=n+m-1;i++) e.ae(idd[n][i]+cnt,T,1,0), e.ae(T,idd[n][i]+cnt,0,0); 87 printf("%d\n",EK()); 88 } 89 }; 90 91 namespace S2{ 92 void solve() 93 { 94 int i,j,da,db; 95 memset(&e,0,sizeof(e)); e.cte=1; 96 for(i=1;i<n;i++) for(j=1;j<=m+i-1;j++) 97 { 98 da=idd[i][j]; 99 db=idd[i+1][j]; e.ae(da,db,1,mp[i+1][j]); e.ae(db,da,0,-mp[i+1][j]); 100 db=idd[i+1][j+1]; e.ae(da,db,1,mp[i+1][j+1]); e.ae(db,da,0,-mp[i+1][j+1]); 101 } 102 for(i=1;i<=m;i++) e.ae(S,i,1,mp[1][i]), e.ae(i,S,0,-mp[1][i]); 103 for(i=1;i<=n+m-1;i++) e.ae(idd[n][i],T,inf,0), e.ae(T,idd[n][i],0,0); 104 printf("%d\n",EK()); 105 } 106 }; 107 108 namespace S3{ 109 void solve() 110 { 111 int i,j,da,db; 112 memset(&e,0,sizeof(e)); e.cte=1; 113 for(i=1;i<=n;i++) for(j=1;j<=m+i-1;j++) 114 { 115 da=idd[i][j]; 116 e.ae(da,da+cnt,inf,mp[i][j]); e.ae(da+cnt,da,0,-mp[i][j]); 117 if(check(i+1,j)) { db=idd[i+1][j]; e.ae(da+cnt,db,inf,0); e.ae(db,da+cnt,0,0); } 118 if(check(i+1,j+1)){ db=idd[i+1][j+1]; e.ae(da+cnt,db,inf,0); e.ae(db,da+cnt,0,0); } 119 } 120 for(i=1;i<=m;i++) e.ae(S,i,1,0), e.ae(i,S,0,0); 121 for(i=1;i<=n+m-1;i++) e.ae(idd[n][i]+cnt,T,inf,0), e.ae(T,idd[n][i]+cnt,0,0); 122 printf("%d\n",EK()); 123 } 124 }; 125 126 int main() 127 { 128 int i,j,da,db; 129 scanf("%d%d",&m,&n); 130 for(i=1;i<=n;i++) for(j=1;j<=m+i-1;j++) mp[i][j]=gint(),idd[i][j]=++cnt; 131 S=0; T=2*cnt+1; S1::solve(); S2::solve(); S3::solve(); 132 return 0; 133 }