zoukankan      html  css  js  c++  java
  • 【模拟试题】困难重重

    【模拟试题】困难重重

    img

    img

    img

    img

    比较容易看出这是个网络流,但是我太菜了不知道怎么建边

    首先如果(A==B),那么就是一个很简单的拆边网络流。先将图黑白染色,(S)向白点连(4)条边,第(i)条边的流量为(1),代价为((i-1)*A);黑点向(T)(4)条边,流量和代价同理。相邻的黑白点之间在连流量为(1)的边。

    然后考虑(Bgeq A)的时候,相当于走了两条横边或者两条竖边过后要额外付出(B-A)的代价。所以我们将一个点再带上两个点分别表示横边和竖边。每个点向一个横点连两条边,流量为(1),代价分别为(0)(B-A)。一个白点的横点向它左右两边的黑点的横点连边,竖点同理。

    遇到这种代价不同的题,一般的做法就是多拆点和建边,将不同的代价的差值表示在边权中。

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define N 155
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    int n,m;
    int A,B;
    int Q;
    char mp[N][N];
    
    struct road {
    	int to,nxt,flow;
    	int c;
    }s[N*N*50];
    
    int h[N*N*3],cnt=1;
    int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
    int id[N][N];
    void add(int i,int j,int f,int c) {
    	s[++cnt]=(road) {j,h[i],f,c};h[i]=cnt;
    	s[++cnt]=(road) {i,h[j],0,-c};h[j]=cnt;
    }
    
    int S,T;
    int dis[N*N*3];
    int fr[N*N*3],e[N*N*3];
    queue<int>q;
    bool in[N*N*3];
    int ans;
    
    bool spfa() {
    	memset(dis,0x3f,sizeof(dis));
    	dis[S]=0;
    	q.push(S);
    	while(!q.empty()) {
    		int v=q.front();
    		q.pop();
    		in[v]=0;
    		for(int i=h[v];i;i=s[i].nxt) {
    			int to=s[i].to;
    			if(s[i].flow&&dis[to]>dis[v]+s[i].c) {
    				dis[to]=dis[v]+s[i].c;
    				e[to]=i;
    				fr[to]=v;
    				if(!in[to]) in[to]=1,q.push(to);
    			}
    		}
    	}
    	if(dis[T]>1e9) return 0;
    	for(int i=T;i;i=fr[i]) {
    		s[e[i]].flow--;
    		s[e[i]^1].flow++;
    	}
    	ans+=dis[T];
    	return 1;
    }
    
    int main() {
    	int type=Get();
    	n=Get(),m=Get();
    	A=Get(),B=Get();
    	for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
    	Q=Get();
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			id[i][j]=(i-1)*m+j;
    	int tot=n*m;
    	T=3*tot+1;
    	for(int i=1;i<=n;i++) {
    		for(int j=1;j<=m;j++) {
    			if(mp[i][j]=='1') continue ;
    			if(!(i+j&1)) {
    				for(int l=1;l<=4;l++) {
    					add(S,id[i][j],1,(l-1)*A);
    				}
    				add(id[i][j],id[i][j]+tot,1,0);
    				add(id[i][j],id[i][j]+tot,1,B-A);
    				add(id[i][j],id[i][j]+2*tot,1,0);
    				add(id[i][j],id[i][j]+2*tot,1,B-A);
    				for(int k=0;k<4;k++) {
    					int a=i+dx[k],b=j+dy[k];
    					if(a<1||a>n||b<1||b>m||mp[a][b]=='1') continue ;
    					if(k<=1) add(id[i][j]+tot,id[a][b]+tot,1,0);
    					else add(id[i][j]+2*tot,id[a][b]+2*tot,1,0);
    				}
    			} else {
    				for(int l=1;l<=4;l++) {
    					add(id[i][j],T,1,(l-1)*A);
    				}
    				add(id[i][j]+tot,id[i][j],1,0);
    				add(id[i][j]+tot,id[i][j],1,B-A);
    				add(id[i][j]+2*tot,id[i][j],1,0);
    				add(id[i][j]+2*tot,id[i][j],1,B-A);
    			}
    		}
    	}
    	if(8<=type&&type<=12) {
    		for(int i=1;i<=Q;i++) {
    			spfa();
    			cout<<(ans>0)<<"
    ";
    		}
    	} else {
    		for(int i=1;i<=Q;i++) {
    			spfa();
    			cout<<ans<<"
    ";
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    8102Java的学习呼声有所下降,2019年还值得学习吗
    大数据开发面试题详解:Hadoop的运行原理
    总结:java大神的自学路线
    大数据开发工程师必看书籍
    java主要编程工具
    bzoj3791 作业
    bzoj3750 [POI2015]Pieczęć
    bzoj1143 [CTSC2008]祭祀river
    bzoj2718 [Violet 4]毕业旅行
    poj3237 Tree
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10615961.html
Copyright © 2011-2022 走看看