1550: Simple String 最大流解法

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1550

很久以前做的一题,当时队友用最大流做,现在我也是

这个转化为二分图多重匹配,就是一样的意思了。

设出一个原点S,两个人1,和2,S-->1的流量是n表明只能流出n个字母,s-->2的流量是n,一样含义。

然后再设一个汇点T,表明需要有多少流进来,跑一发就好。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 100000 * 2;
struct Edge {
    int u, v, w, tonext;
    int id;
}e[maxn * 2];
int first[maxn], num;
void addEdge(int u, int v, int w) {
    e[num].u = u, e[num].v = v, e[num].w = w, e[num].tonext = first[u], e[num].id = num;
    first[u] = num++;
}
int flow[maxn], pre[maxn];
int bfs(int be, int en) { //O(n * E * E)
    queue<int> que;
    memset(flow, false, sizeof flow);
    pre[be] = -1, flow[be] = inf;
    que.push(be);
    while (!que.empty()) {
        int cur = que.front();
        que.pop();
        for (int i = first[cur]; ~i; i = e[i].tonext) {
            int v = e[i].v;
            if (flow[v] == 0 && e[i].w > 0) {
                pre[v] = e[i].id;
                flow[v] = min(flow[cur], e[i].w);
                que.push(v);
            }
        }
        if (flow[en]) break; //找到了增广路
    }
    if (flow[en] == 0) return -1;
    else return flow[en];
}

int maxFlow(int be, int en) {
    int sumFlow = 0;
    while (true) {
        int res = bfs(be, en);
        if (res == -1) { //找不到增广路
            break;
        }
        int edgeID = pre[en];
        while (edgeID != -1) {
            e[edgeID].w -= res;
            e[edgeID ^ 1].w += res;
            edgeID = pre[e[edgeID].u];
        }
        sumFlow += res;
    }
    return sumFlow;
}
char s1[maxn], s2[maxn], s3[maxn];
int cnt1[222], cnt2[222], cnt3[222];
void work() {
    memset(cnt1, 0, sizeof cnt1);
    memset(cnt2, 0, sizeof cnt2);
    memset(cnt3, 0, sizeof cnt3);
    memset(first, -1, sizeof first);
    num = 0;
    int lenstr = strlen(s1 + 1);
    addEdge(0, 1, lenstr / 2);
    addEdge(1, 0, 0);
    addEdge(0, 2, lenstr / 2);
    addEdge(2, 0, 0);
    for (int i = 1; i <= lenstr; ++i) {
        cnt1[s1[i]]++;
        cnt2[s2[i]]++;
        cnt3[s3[i]]++;
    }
    for (int i = ‘A‘; i <= ‘Z‘; ++i) {
        addEdge(1, i - ‘A‘ + 3, cnt1[i]);
        addEdge(i - ‘A‘ + 3, 1, 0);
        addEdge(2, i - ‘A‘ + 3, cnt2[i]);
        addEdge(i - ‘A‘ + 3, 2, cnt2[i]);
    }
    for (int i = ‘A‘; i <= ‘Z‘; ++i) {
        addEdge(i - ‘A‘ + 3, 29, cnt3[i]);
        addEdge(29, i - ‘A‘ + 3, 0);
    }
    int res = maxFlow(0, 29);
    if (res == lenstr) {
        printf("YES\n");
    } else printf("NO\n");
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    while (scanf("%s%s%s", s1 + 1, s2 + 1, s3 + 1) > 0) work();
    return 0;
}

时间: 2024-10-12 17:03:22

1550: Simple String 最大流解法的相关文章

csu 1550: Simple String (字符串)

1550: Simple String Time Limit: 1 Sec  Memory Limit: 256 MB Submit: 249  Solved: 112 [Submit][Status][Web Board] Description Welcome,this is the 2015 3th Multiple Universities Programming Contest ,Changsha ,Hunan Province. In order to let you feel fu

Water --- CSU 1550: Simple String

Simple String Problem's Link:   http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1550 Mean: 略. analyse: 水题. Time complexity: O(n) Source code:  // Memory Time // 1347K 0MS // by : crazyacking // 2015-03-29-12.08 #include<map> #include<queue> #

(比赛)A - Simple String Problem

A - Simple String Problem Time Limit:10000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Practice POJ 2236 Description An earthquake takes place in Southeast Asia. The ACM (Asia Cooperated Medical team) have set up a wireless network wit

线性规划费用流解法(Bzoj1061: [Noi2008]志愿者招募)

题面 传送门 Sol 线性规划费用流解法用与求解未知数为非负数的问题 这道题可以列出一堆形如 \(x[i]+x[j]+x[k]+...>=a[p]\) 的不等式 我们强行给每个式子减去一个东西,使他变成这样 \(x[i]+x[j]+x[k]+...-y[p]==a[p]\) 然后相邻两个式子差分一下 把每个式子看成一个点 那么这样后,在这个题中所有的未知数只会出现在一个方程中 等式左边符号是正的向符号为负的方程连边,费用为代价,如果是补的未知数\(y\),那么费用为零 右边的数是正的连\(s\)

D - Simple String CSU - 1550

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1550 很久都没补这题,最近想学网络流,就看看,队友以前用网络流过的,Orz, 但是这题只需要简单的判断,可能想起来有点麻烦. 考虑一定要从A串取出n个,B串也一定要取出n个,那么A和C的交集一定要大于等于n,同理B. 同时为了得到C串,还需要A + B和C的交集一定要大于等于n * 2 怎么说呢.可以画个图表示下,反正找不到反例.就先码一波. #include <cstdio> #incl

delphi 怎么将一个文件流转换成字符串(String到流,String到文件,相互转化)

//from   http://kingron.myetang.com/zsfunc0d.htm (*//   标题:充分利用pascal字符串类型   说明:和PChar不同,string可以保存#0字符在其中;示例文件.内存流字符串之间转换   设计:Zswang   日期:2002-01-25   支持:[email protected]   //*) ///////Begin   Source   function   StringToFile(mString:   string;  

有上下界的最大流解法

问题模型: 给定一个加权的有向图,满足: (1)容量限制条件: (2)流量平衡条件: (2)中的即除了源汇外,所有点都满足流量平衡条件,则称G为有源汇网络:否则,即不存在源汇,所有点都满足流量平衡条件,则称G为无源汇网络. 将这类问题由易到难一一解决: 问题[1] 求无源汇的网络有上下界的可行流 由于下界是一条弧上的流必需要满足的确定值.下面引入必要弧的概念:必要弧是一定流要满的弧.必要弧的构造,将容量下界的限制分离开了,从而构造了一个没有下界的网络G': 1. 将原弧(u,v)分离出一条必要弧

codevs.cn 2776寻找代表元 最大流解法

网址:http://codevs.cn/problem/2776/ 题目大意: n个社团,m个人,每个社团可以有一个人担任代表,每个人可以担任多个代表,问最多有多少人是代表. 思路:可以建一个图,然后最大流(废话).怎么建图? 先膜下神犇 orz QZZ. 样例的图大概是这样的: 图丑就不要在意啦. s为源点,t为汇点 图中可以看出n个社团与s建一条流量为 1 的边(每个社团只选一个代表,1为限制条件),然后按照读入数据与每个人建一条流量为 1 的边(社团选了这个人就不能选了),最后每个人和t建

[Coding Made Simple] String Interleaving

Given three strings, return true if third string is interleaving of first and second string. By running some examples, it seems that as long as s1.length() + s2.length() == s3.length() and both s1 and s2 are common subsequences of s3, s3 is interleav