Educational Codeforces Round 47 (Rated for Div. 2)G. Allowed Letters 网络流

题意:给你一个字符串,和每个位置可能的字符(没有就可以放任意字符)要求一个排列使得每个位置的字符在可能的字符中,求字典序最小的那个
题解:很容易判断有没有解,建6个点表示从a-f,和源点连边,容量为原串字符出现次数,再建64个点表示给定的位置的每一个状态,和汇点连边,容量为出现次数,如果a-f某个字符在状态中出现过,再把a-f和状态连边,容量inf,但是这只能求可行解,并不是字典序最小,
我们枚举每个位置该放哪个字符(a-f),假设该位置是pos,枚举的字符是x,该位置可能字符的状态是st,现在流量是s->x->st->t,如果这条路上最小流量不是0,我们把这条路往回流1然后,把容量缩小1,判断后面的字符是不是可行,如果可行,那么我们就在该位置放x,(从小到大枚举,贪心的放),
现在有一个问题就是虽然s->x,st->t可能有流量,但是x到st不一定流量,所以我们枚举x到达的每一个状态,然后回流1,再枚举st对应的每个字符,回流1,最后统一增广
还好这题图是个二分图,不然回流可能写死人
虽然我写了当前弧优化,还是没用,不加编译优化会t!!!

#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=73+10,maxn=1500+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

struct edge{
    int to,Next,c,cc;
}e[maxn];
int s,t,cnt,head[N],cur[N];
vi v[N],rev[N];
void init()
{
    cnt=0;
    memset(head,-1,sizeof head);
}
void add(int u,int v,int c)
{
    e[cnt].to=v;
    e[cnt].c=c;
    e[cnt].cc=c;
    e[cnt].Next=head[u];
    head[u]=cnt++;
    e[cnt].to=u;
    e[cnt].c=0;
    e[cnt].cc=0;
    e[cnt].Next=head[v];
    head[v]=cnt++;
}
int dis[N];
bool bfs()
{
    queue<int>q;
    memset(dis,-1,sizeof dis);
    dis[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=head[x];~i;i=e[i].Next)
        {
            int y=e[i].to;
            if(dis[y]==-1&&e[i].c>0)
            {
                dis[y]=dis[x]+1;
                q.push(y);
            }
        }
    }
    return dis[t]!=-1;
}
int dfs(int u,int mx)
{
    if(u==t)return mx;
    int f;
    for(int &i=cur[u];~i;i=e[i].Next)
    {
        int x=e[i].to;
        if(dis[x]==dis[u]+1&&e[i].c>0&&(f=dfs(x,min(mx,e[i].c))))
        {
            e[i].c-=f;
            e[i^1].c+=f;
            return f;
        }
    }
    return 0;
}
int maxflow()
{
    int ans=0,f;
    while(bfs())
    {
        for(int i=0;i<=t;i++)cur[i]=head[i];
        while((f=dfs(s,inf)))ans+=f;
    }
    return ans;
}
void calcelflow(int be,int en)
{

}
char c[100010],cc[10];
int mask[100010],a[10],num[100];
int id[100][100];
int main()
{
    scanf("%s",c);
    int n=strlen(c),m;
    for(int i=0;i<n;i++)a[c[i]-'a']++;
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        int id;
        scanf("%d%s",&id,cc);id--;
        int len=strlen(cc);
        for(int j=0;j<len;j++)mask[id]|=(1<<(cc[j]-'a'));
        if(!mask[id])mask[id]=(1<<6)-1;
        num[mask[id]]++;
    }
    for(int i=0;i<n;i++)
        if(!mask[i])
            num[mask[i]=(1<<6)-1]++;
    s=6+(1<<6),t=6+(1<<6)+1;
    init();
    for(int i=0;i<6;i++)id[s][i]=cnt,add(s,i,a[i]);
    for(int i=0;i<(1<<6);i++)id[i+6][t]=cnt,add(i+6,t,num[i]);
    for(int i=0;i<(1<<6);i++)
        for(int j=0;j<6;j++)
            if((i>>j)&1)
                v[j].pb(i),rev[i].pb(j),
                id[j][i+6]=cnt,add(j,i+6,inf);
    int ans=maxflow();
    for(int i=0;i<n;i++)
    {
        bool ok=1;
        for(int j=0;j<6;j++)
        {
            if(!((mask[i]>>j)&1))continue;
            if(e[id[s][j]+1].c==0||e[id[mask[i]+6][t]+1].c==0)continue;
            for(int k=0;k<rev[mask[i]].size();k++)
            {
                int x=rev[mask[i]][k];
                if(e[id[x][mask[i]+6]+1].c!=0&&e[id[s][x]+1].c!=0)
                {
                    int mi=min(e[id[x][mask[i]+6]+1].c,min(e[id[s][x]+1].c,e[id[mask[i]+6][t]+1].c));
                    e[id[s][x]+1].c-=1;
                    e[id[x][mask[i]+6]+1].c-=1;
                    e[id[mask[i]+6][t]+1].c-=1;
                    e[id[s][x]].c+=1;
                    e[id[x][mask[i]+6]].c+=1;
                    e[id[mask[i]+6][t]].c+=1;
                    ans-=1;
                    break;
                }
            }
            for(int k=0;k<v[j].size();k++)
            {
                int x=v[j][k];
                if(e[id[j][x+6]+1].c!=0&&e[id[x+6][t]+1].c!=0)
                {
                    int mi=min(e[id[s][j]+1].c,min(e[id[j][x+6]+1].c,e[id[x+6][t]+1].c));
                    e[id[s][j]+1].c-=1;
                    e[id[j][x+6]+1].c-=1;
                    e[id[x+6][t]+1].c-=1;
                    e[id[s][j]].c+=1;
                    e[id[j][x+6]].c+=1;
                    e[id[x+6][t]].c+=1;
                    ans-=1;
                    break;
                }
            }
            if(e[id[s][j]].c==0||e[id[j][mask[i]+6]].c==0||e[id[mask[i]+6][t]].c==0)continue;
            e[id[s][j]].c--,e[id[j][mask[i]+6]].c--,e[id[mask[i]+6][t]].c--;
            ans+=maxflow();
            if(ans==n-i-1)
            {
                c[i]=j+'a';
                ok=0;
                break;
            }
            else e[id[s][j]].c++,e[id[j][mask[i]+6]].c++,e[id[mask[i]+6][t]].c++,ans+=maxflow();
        }
        if(ok)return 0*puts("Impossible");
    }
    printf("%s\n",c);
    return 0;
}
/***********************
bedefead
5
2 e
1 dc
5 b
7 ef
6 ef
***********************/

原文地址:https://www.cnblogs.com/acjiumeng/p/9339062.html

时间: 2024-08-26 06:55:04

Educational Codeforces Round 47 (Rated for Div. 2)G. Allowed Letters 网络流的相关文章

Educational Codeforces Round 47 (Rated for Div. 2) :E. Intercity Travelling

题目链接:http://codeforces.com/contest/1009/problem/E 解题心得: 一个比较简单的组合数学,还需要找一些规律,自己把方向想得差不多了但是硬是找不到规律,还是看了大佬博客才知道的规律.这个题要预先处理2的n次方,不然快速幂也会TLE. 推荐两个大佬的博客: https://blog.csdn.net/u010746456/article/details/81057082 https://blog.csdn.net/hyp1231/article/deta

Educational Codeforces Round 47 (Rated for Div. 2)F. Dominant Indices 线段树合并

题意:有一棵树,对于每个点求子树中离他深度最多的深度是多少, 题解:线段树合并快如闪电,每个节点开一个权值线段树,递归时合并即可,然后维护区间最多的是哪个权值,到x的深度就是到根的深度减去x到根的深度复杂度O(nlogn) //#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("

Educational Codeforces Round 41 (Rated for Div. 2) G. Partitions

G. Partitions time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a set of n elements indexed from 1 to n. The weight of i-th element is wi. The weight of some subset of a given

Educational Codeforces Round 36 (Rated for Div. 2) G. Coprime Arrays

求a_i 在 [1,k]范围内,gcd(a_1,a_2...,a_n) = 1的a的数组个数. F(x)表示gcd(a_1,a_2,...,a_n) = i的a的个数 f(x)表示gcd(a_1,a_2,...,a_n) = ki的a的个数(实际上就是i的倍数) f(x) = segma(x | d) F(d) F(x) = segma(x | d) mu(d / x) * f(d) F(1) = segma(d,1,k) mu(d) * f(d) f(d) = (k / d)^n 由于k变化时

Educational Codeforces Round 48 (Rated for Div. 2)G. Appropriate Team

题意:求满足条件的(i,j)对数:\(gcd(v,a_i)=x,lcm(v,a_j)=y\) 题解:\(x|a_i,a_j|y\),\(x|y\),考虑质因子p,假设a_i中p次数为a,x中次数为b,y为c,\(a_j\)为d;a>=b,c>=d. 假设a>b,c>d,那么由于\(gcd(v,a_i)=x\),v中p的次数为b,由于\(lcm(v,a_j)=y\),那么\(max(b,d)==c\),又c>d,所以b=c<a和x|y矛盾,所以此时ij不满足条件 其他情况

Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)

#include<bits/stdc++.h>using namespace std;int st[1000007];int top;int s[1000007],t[1000007];int mx[4000007];int sum[4000007];int head[1000007],to[2000007],nex[2000007];int n,k;int a[10000077];int dfn;int tot;void pushup(int rt){    mx[rt]=max(mx[rt

Educational Codeforces Round 53 (Rated for Div. 2)G. Yet Another LCP Problem

题意:给串s,每次询问k个数a,l个数b,问a和b作为后缀的lcp的综合 题解:和bzoj3879类似,反向sam日神仙...lcp就是fail树上的lca.把点抠出来建虚树,然后在上面dp即可.(感觉之前写的svt什么玩意) //#pragma GCC optimize(2) //#pragma GCC optimize(3) //#pragma GCC optimize(4) //#pragma GCC optimize("unroll-loops") //#pragma comm

Educational Codeforces Round 36 (Rated for Div. 2)

Educational Codeforces Round 36 (Rated for Div. 2) F. Imbalance Value of a Tree You are given a tree T consisting of n vertices. A number is written on each vertex; the number written on vertex i is ai. Let's denote the function I(x,?y) as the differ

Educational Codeforces Round 69 (Rated for Div. 2) B - Pillars

Educational Codeforces Round 69 (Rated for Div. 2) B - Pillars There are n pillars aligned in a row and numbered from 1 to n. Initially each pillar contains exactly one disk. The i-th pillar contains a disk having radius ai. You can move these disks