• AtCoder


    There is a pond with a rectangular shape. The pond is divided into a grid with H rows and W columns of squares. We will denote the square at the i-th row from the top and j-th column from the left by (ij).

    Some of the squares in the pond contains a lotus leaf floating on the water. On one of those leaves, S, there is a frog trying to get to another leaf T. The state of square (ij) is given to you by a character aij, as follows:

    • . : A square without a leaf.
    • o : A square with a leaf floating on the water.
    • S : A square with the leaf S.
    • T : A square with the leaf T.

    The frog will repeatedly perform the following action to get to the leaf T: "jump to a leaf that is in the same row or the same column as the leaf where the frog is currently located."

    Snuke is trying to remove some of the leaves, other than S and T, so that the frog cannot get to the leaf T. Determine whether this objective is achievable. If it is achievable, find the minimum necessary number of leaves to remove.


    Constraints
    • 2H,W100
    • aij is ., o, S or T.
    • There is exactly one S among aij.
    • There is exactly one T among aij.
    Input

    Input is given from Standard Input in the following format:

    H W
    a11  a1W
    :
    aH1  aHW
    
    Output

    If the objective is achievable, print the minimum necessary number of leaves to remove. Otherwise, print -1 instead.

    Sample Input 1
    3 3
    S.o
    .o.
    o.T
    
    Sample Output 1
    2
    

    Remove the upper-right and lower-left leaves.

    Sample Input 2
    3 4
    S...
    .oo.
    ...T
    
    Sample Output 2
    0
    
    Sample Input 3
    4 3
    .S.
    .o.
    .o.
    .T.
    
    Sample Output 3
    -1
    
    Sample Input 4
    10 10
    .o...o..o.
    ....o.....
    ....oo.oo.
    ..oooo..o.
    ....oo....
    ..o..o....
    o..o....So
    o....T....
    ....o.....
    ........oo
    
    Sample Output 4
    5
    
    有意思的网络流题目;
    刚开始我想的很直接:按题目建边,但是你会发现这样建边之后复杂度会很高,而且也不现实;
    我们考虑将行和列分开;
    对于源点,我们将其和该行建边,与该列建边;
    同理对于汇点;
    对于O这种情况,我们将行和列建边,容量为1;
    由于我们要使得S,T分开,所以要求的是最小割,那么就是dinic求一下最大流即可;
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<map>
    #include<set>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<ctime>
    #include<deque>
    #include<stack>
    #include<functional>
    #include<sstream>
    //#include<cctype>
    //#pragma GCC optimize(2)
    using namespace std;
    #define maxn 2000005
    #define inf 0x7fffffff
    //#define INF 1e18
    #define rdint(x) scanf("%d",&x)
    #define rdllt(x) scanf("%lld",&x)
    #define rdult(x) scanf("%lu",&x)
    #define rdlf(x) scanf("%lf",&x)
    #define rdstr(x) scanf("%s",x)
    typedef long long  ll;
    typedef unsigned long long ull;
    typedef unsigned int U;
    #define ms(x) memset((x),0,sizeof(x))
    const long long int mod = 1e9 + 7;
    #define Mod 1000000000
    #define sq(x) (x)*(x)
    #define eps 1e-4
    typedef pair<int, int> pii;
    #define pi acos(-1.0)
    //const int N = 1005;
    #define REP(i,n) for(int i=0;i<(n);i++)
    typedef pair<int, int> pii;
    inline ll rd() {
    	ll x = 0;
    	char c = getchar();
    	bool f = false;
    	while (!isdigit(c)) {
    		if (c == '-') f = true;
    		c = getchar();
    	}
    	while (isdigit(c)) {
    		x = (x << 1) + (x << 3) + (c ^ 48);
    		c = getchar();
    	}
    	return f ? -x : x;
    }
    
    ll gcd(ll a, ll b) {
    	return b == 0 ? a : gcd(b, a%b);
    }
    int sqr(int x) { return x * x; }
    
    
    /*ll ans;
    ll exgcd(ll a, ll b, ll &x, ll &y) {
    	if (!b) {
    		x = 1; y = 0; return a;
    	}
    	ans = exgcd(b, a%b, x, y);
    	ll t = x; x = y; y = t - a / b * y;
    	return ans;
    }
    */
    
    int n, m;
    int st, ed;
    struct node {
    	int u, v, nxt, w;
    }edge[maxn << 1];
    
    int head[maxn], cnt;
    
    void addedge(int u, int v, int w) {
    	edge[cnt].u = u; edge[cnt].v = v; edge[cnt].nxt = head[u];
    	edge[cnt].w = w; head[u] = cnt++;
    }
    
    int rk[maxn];
    
    int bfs() {
    	queue<int>q;
    	ms(rk);
    	rk[st] = 1;
    	q.push(st);
    	while (!q.empty()) {
    		int tmp = q.front(); q.pop();
    		for (int i = head[tmp]; i != -1; i = edge[i].nxt) {
    			int to = edge[i].v;
    			if (rk[to] || edge[i].w <= 0)continue;
    			rk[to] = rk[tmp] + 1; q.push(to);
    		}
    	}
    	return rk[ed];
    }
    
    int dfs(int u, int flow) {
    	if (u == ed)return flow;
    	int add = 0;
    	for (int i = head[u]; i != -1 && add < flow; i = edge[i].nxt) {
    		int v = edge[i].v;
    		if (rk[v] != rk[u] + 1 || !edge[i].w)continue;
    		int tmpadd = dfs(v, min(edge[i].w, flow - add));
    		if (!tmpadd) { rk[v] = -1; continue; }
    		edge[i].w -= tmpadd; edge[i ^ 1].w += tmpadd;
    		add += tmpadd;
    	}
    	return add;
    }
    
    int ans;
    void dinic() {
    	while (bfs())ans += dfs(st, inf);
    }
    int H, W;
    char ch[103][103];
    
    int getpos(int x, int y) {
    	return (x - 1)*W + y;
    }
    int main() {
    //	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    	cin >> H >> W; memset(head, -1, sizeof(head));
    	for (int i = 1; i <= H; i++)scanf("%s", ch[i] + 1);
    	int hx = 0, hy = 0, wx = 0, wy = 0;
    	for (int i = 1; i <= H; i++) {
    		for (int j = 1; j <= W; j++) {
    			if (ch[i][j] == 'S') {
    				hx = i; hy = j;
    			}
    			else if (ch[i][j] == 'T') {
    				wx = i; wy = j;
    			}
    		}
    	}
    	if (wx == hx || wy == hy) {
    		cout << -1 << endl; return 0;
    	}
    	st = 0; ed = H * W + 1;
    	for (int i = 1; i <= H; i++) {
    		for (int j = 1; j <= W; j++) {
    			if (ch[i][j] == 'S')addedge(st, i, inf), addedge(i, st, 0), addedge(st, j + H, inf), addedge(j + H, st, 0);
    			if (ch[i][j] == 'T')addedge(i, ed, inf), addedge(ed, i, 0), addedge(j + H, ed, inf), addedge(ed, j + H, 0);
    			if (ch[i][j] != '.')addedge(i, j + H, 1), addedge(j + H, i, 0), addedge(j + H, i, 1), addedge(i, j + H, 0);
    
    		}
    	}
    	dinic();
    	if (ans != inf) {
    		cout << ans << endl; return 0;
    	}
    	else cout << -1 << endl;
    	return 0;
    }
    
    
    
    EPFL - Fighting
  • 相关阅读:
    Ajax | Form 上传图片文件
    .NET Core 上传图片到七牛云
    限制input输入框只能输入 数字
    MySql操作命令创建学生管理系统
    大数据之kafka-05.讲聊聊Kafka的版本号
    大数据之kafka-02.搞定kafka专业术语
    消息队列的作用以及kafka和activemq的对比
    .Net Core 3.1迁移整理
    RabbitMQ的使用
    .NET Framework 项目多环境下配置文件web.config
  • 原文地址:https://www.cnblogs.com/zxyqzy/p/10319374.html
Copyright © 2020-2023  润新知