• 【bzoj2893】征服王


    比较明显的缩点,变成dag上最小路径覆盖,指定了起点终点所以建模有一些变化。

    跑费用流,增广的次数即为答案。

    #include<bits/stdc++.h>
    #define maxn 5005
    #define maxm 100005
    #define INF 0x7f7f7f7f
    using namespace std;
     
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
     
    struct scsc{
        int next,from,to,w,c;
    }edge[maxm<<1];
     
    struct _scsc{
        int next,to;
    }_edge[maxm<<1];
     
    int n,m,_Len,Len,scc,top,Time,_head[maxn],head[maxn],dfn[maxn],low[maxn],s[maxn],vis[maxn],hav[maxn],belong[maxn],p[maxn][2];
    int sss,ttt,ss[maxn],tt[maxn],d[maxn],pre[maxn];
     
    void addedge(int u,int v,int w,int c){
        edge[++Len].to=v;edge[Len].from=u;edge[Len].next=head[u];edge[Len].w=w;edge[Len].c=c;head[u]=Len;
        edge[++Len].to=u;edge[Len].from=v;edge[Len].next=head[v];edge[Len].w=0;edge[Len].c=-c;head[v]=Len;
    }
     
    void _addedge(int u,int v){
        _edge[++_Len].to=v;_edge[_Len].next=_head[u];_head[u]=_Len;
    }
     
    void tarjan(int u){
        dfn[u]=low[u]=++Time;
        s[++top]=u;vis[u]=1;
        for(int i=_head[u];i;i=_edge[i].next){
            int v=_edge[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }else
            if(vis[v])low[u]=min(low[u],dfn[v]);
        }
        int now=0;
        if(dfn[u]==low[u]){
            ++scc;
            while(now!=u){
                now=s[top--];
                vis[now]=0;
                ++hav[scc];
                belong[now]=scc;
            }
        }
    }
     
    int id=0;
     
    void rebuild(int s,int t){
        for(int i=1;i<=scc;++i)p[i][0]=++id,p[i][1]=++id;
        for(int i=1;i<=sss;++i)addedge(s,p[belong[ss[i]]][0],INF,0);
        for(int i=1;i<=ttt;++i)addedge(p[belong[tt[i]]][1],t,INF,0);
        for(int i=1;i<=scc;++i)addedge(p[i][0],p[i][1],1,1),addedge(p[i][0],p[i][1],INF,0);
        for(int u=1;u<=n;++u){
            for(int i=_head[u];i;i=_edge[i].next){
                int v=_edge[i].to;
                if(belong[u]!=belong[v])
                    addedge(p[belong[u]][1],p[belong[v]][0],INF,0);
            }
        }
    }
     
    int spfa(int s,int t){
        queue<int>Q;
        memset(d,-1,sizeof(d));
        Q.push(s);vis[s]=1;d[s]=0;
        while(!Q.empty()){
            int u=Q.front();Q.pop();
            for(int i=head[u];i;i=edge[i].next){
                int v=edge[i].to;
                if(edge[i].w&&d[v]<d[u]+edge[i].c){
                    d[v]=d[u]+edge[i].c;pre[v]=i;
                    if(!vis[v]){
                        vis[v]=1;
                        Q.push(v);
                    }
                }
            }
            vis[u]=0;
        }
        return d[t]!=-1;
    }
     
    int mcmf(int s,int t){
        int ret=0,now=0,last=0;
        while(spfa(s,t)){
            int w=INF;last=now;
            for(int i=pre[t];i;i=pre[edge[i].from])w=min(w,edge[i].w);
            for(int i=pre[t];i;i=pre[edge[i].from]){
                edge[i].w-=w;
                edge[i^1].w+=w;
                now+=w*edge[i].c;
            }
            if(now==last)break;
            ++ret;
        }
        if(now!=scc)return -1;
        return ret;
    }
     
    void Init(){
        Len=1;memset(head,0,sizeof(head));id=scc=0;
        _Len=0;memset(_head,0,sizeof(_head));
        memset(pre,0,sizeof(pre));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        int f1,f2;
        n=read();m=read();sss=read();ttt=read();
        for(int i=1;i<=sss;++i)ss[i]=read();
        for(int i=1;i<=ttt;++i)tt[i]=read();
        for(int i=1;i<=m;++i){
            f1=read();f2=read();
            _addedge(f1,f2);
        }
    }
     
    void WoRk(){
        for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i);
        int s=0,t=2*n+1;
        rebuild(s,t);
        int ans=mcmf(s,t);
        if(ans==-1)printf("no solution
    ");else printf("%d
    ",ans);
    }
     
    int main(){
        int t=read();
        while(t--){
            Init();
            WoRk();
        }
        return 0;
    }
  • 相关阅读:
    java八大数据类型
    变量,常量,作用域
    位运算符
    可变参数
    重写
    javascript中各种循环总结
    前端高效emmit快捷键
    移动端列表页布局
    sublime text3中添加插件CSScomb方法
    友元类头文件互相包含问题
  • 原文地址:https://www.cnblogs.com/illya/p/7581050.html
Copyright © 2020-2023  润新知