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;
    }
    
    
  • 相关阅读:
    LeetCode 230. Kth Smallest Element in a BST
    LeetCode 114. Flatten Binary Tree to Linked List
    LeetCode 222. Count Complete Tree Nodes
    LeetCode 129. Sum Root to Leaf Numbers
    LeetCode 113. Path Sum II
    LeetCode 257. Binary Tree Paths
    Java Convert String & Int
    Java Annotations
    LeetCode 236. Lowest Common Ancestor of a Binary Tree
    LeetCode 235. Lowest Common Ancestor of a Binary Search Tree
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10615961.html
Copyright © 2011-2022 走看看