zoukankan      html  css  js  c++  java
  • Risk UVA

    /**
    题目:Risk UVA - 12264
    链接:https://vjudge.net/problem/UVA-12264
    题意:给n个点的无权无向图(n<=100),每个点有一个非负数ai。
    若ai==0则此点归敌方所有,若ai>0则此点归你且上面有ai个属于你的士兵。
    保证至少有一个属于你的点与敌方的点相邻。你可以让你的每个士兵最多移动一次
    ,每次可以待在原地或者去到相邻的属于你的领地,但每个点至少要留1各士兵,
    使得最薄弱的关口尽量坚固。关口是指与敌方点相邻的点,薄弱与坚固分别指兵少与兵多。
    
    思路:拆点法+最大流+二分。
    
    将点x,拆分成x,x'。
    s->x,容量为初始士兵数量。
    x'->t。 如果x是薄弱点,那么容量为mid,否则容量为1。1是为了满足题目至少留一个兵。
    x->x',容量为INF。
    
    如果x与y相邻,x->y',容量为INF。
    
    
    上面的容量为mid,就是假如所有的薄弱点都为mid个士兵,是否可行,如果可行,那么增加mid,找一个满足的最大的mid。
    
    二分mid。
    
    如果最大流=薄弱点数量*mid+(自己的领地结点数-薄弱点数量)*1。那么可行。
    
    注意:原题题意给出的输入输出要求是没有问题的,不过题目的实际输入输出有点问题。照着题意要求做就行。
    
    */
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<map>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const long long MAS = 1e13;
    const int INF = 0x3f3f3f3f;
    typedef long long LL;
    const int N = 205;///拆点法,注意要乘以个2.
    struct Edge{
        int from, to, cap, flow;
        Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
    };
    struct Dinic{
        int n, m, s, t;
        vector<Edge> edges;
        vector<int> G[N];
        bool vis[N];
        int d[N];
        int cur[N];
    
        void init(int n)
        {
            this->n = n;
            for(int i = 0; i <= n; i++) G[i].clear();
            edges.clear();
        }
    
        void AddEdge(int from,int to,int cap)
        {
            edges.push_back(Edge(from,to,cap,0));
            edges.push_back(Edge(to,from,0,0));
            m = edges.size();
            G[from].push_back(m-2);
            G[to].push_back(m-1);
        }
    
        bool BFS()
        {
            memset(vis, 0, sizeof vis);
            queue<int> Q;
            Q.push(s);
            d[s] = 0;
            vis[s] = 1;
            while(!Q.empty())
            {
                int x = Q.front();
                Q.pop();
                for(int i = 0; i < G[x].size(); i++)
                {
                    Edge &e = edges[G[x][i]];
                    if(!vis[e.to]&&e.cap>e.flow)
                    {
                        vis[e.to] = 1;
                        d[e.to] = d[x]+1;
                        Q.push(e.to);
                    }
                }
            }
            return vis[t];
        }
    
        int DFS(int x,int a)
        {
            if(x==t||a==0) return a;
            int flow = 0, f;
            for(int &i = cur[x]; i < G[x].size(); i++)
            {
                Edge& e = edges[G[x][i]];
                if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0)
                {
                    e.flow += f;
                    edges[G[x][i]^1].flow -= f;
                    flow += f;
                    a -= f;
                    if(a==0) break;
                }
            }
            return flow;
        }
    
        int Maxflow(int s,int t)
        {
            this->s = s, this->t = t;
            int flow = 0;
            while(BFS())
            {
                memset(cur, 0, sizeof cur);
                flow += DFS(s,INF);
            }
            return flow;
        }
    };
    char str[N][N];
    int sd[N], f[N][N];
    int weak[N], enemy[N];
    int main()
    {
        int n, k;
        cin>>k;
        while(k--){
            scanf("%d",&n);
            memset(enemy, 0, sizeof enemy);
            for(int i = 1; i <= n; i++){
                scanf("%d",&sd[i]);
                if(sd[i]==0) enemy[i] = 1;///敌人结点
            }
            memset(f, 0, sizeof f);
            memset(weak, 0, sizeof weak);
            for(int i = 1; i <= n; i++){
                scanf("%s",str[i]+1);
                for(int j = 1; j <= n; j++){
                    if(str[i][j]=='Y'){
                        f[i][j] = 1;
                        if(enemy[i]&&enemy[j]==0){
                            weak[j] = 1;///薄弱结点
                        }
                        if(enemy[i]==0&&enemy[j]){
                            weak[i] = 1;///薄弱结点
                        }
                    }
                }
            }
            int s = 0, t = n*2+1;
            Dinic dinic, save;
            dinic.init(t);
            for(int i = 1; i <= n; i++){
                if(enemy[i]) continue;
                dinic.AddEdge(s,i,sd[i]);
                dinic.AddEdge(i,i+n,INF);
                if(weak[i]==0){
                    dinic.AddEdge(i+n,t,1);
                }
            }
            for(int i = 1; i <= n; i++){
                if(enemy[i]) continue;
                for(int j = 1; j <= n; j++){
                    if(enemy[j]) continue;
                    if(f[i][j]){
                        dinic.AddEdge(i,j+n,INF);
                    }
                }
            }
    
            save = dinic;
            int weaknum = 0, total = 0;
            for(int i = 1; i <= n; i++){
                if(weak[i]) weaknum++;
                if(enemy[i]==0) total++;
            }
            int lo = 0, hi = INF, mid;
            int ans;
            while(lo<=hi){
                mid = (lo+hi)/2;
                dinic = save;
                for(int i = 1; i <= n; i++){
                    if(weak[i]){
                        dinic.AddEdge(i+n,t,mid);
                    }
                }
                int mas = dinic.Maxflow(s,t);
                int sum = weaknum*mid+(total-weaknum);
                if(mas==sum){
                    lo = mid+1;
                    ans = mid;
                }else
                {
                    hi = mid-1;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    玲珑oj 1129 ST
    HDU 3397 线段树区间修改
    bzoj 1798 双标记区间修改线段树
    HDU 4417 BIT or ST
    HDU 2492 BIT/逆序数/排列组合
    uva 12086 线段树or树状数组练习
    cf 833 A 数论
    wcf的DataContractAttribute与DataMenmberAttribute
    wcf服务查看工具
    git学习-综合性文章
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7214219.html
Copyright © 2011-2022 走看看