zoukankan      html  css  js  c++  java
  • vijos P1352 最大获利(最小割)

    请不要随便指点别人该怎么做、每一个人的人生都应该自己掌握、你给不了别人一切、你也不懂别人的忧伤、

                                                                                              微笑不代表快乐、哭泣不一定悲伤

                   不努力怎么让关心你的人幸福、不努力怎么让看不起你的人绝望、

                                                                                                                                        

                                                                                                                                                                  我用生命在奋斗——lx_Zz

    —————————————————————————————————————————————————————————————

    —————————————————————————    华丽的切割线    ————————————————————————————

    —————————————————————————————————————————————————————————————

    敬仰完《最小割模型在信息学中的应用》论文之后切一下例题、发现自己太弱了。

    。。。orz

    /* 题目: vijos 1352  */
    /* 作者: lx_Zz       */
    /* 时间: 2014.5.20   */
    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<algorithm>
    using namespace std;
    #define N 60005
    #define INF 0x7fffffff
    int n,m,k;
    int level[N];
    struct node
    {
        int to,next,cost;
    }edge[500005];
    int num[N];
    int head[N];
    int t_head[N];
    int start,end;
    void init()
    {
        k=0;
        memset(head,-1,sizeof(head));
    }
    int bfs(int s,int t)//对顶点进行标号、找出层次图
    {
        memset(level,0,sizeof(level));
        queue<int>q;
        q.push(s);
        level[s]=1;
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
            for(int i=head[now];i!=-1;i=edge[i].next)
            {
                int y=edge[i].to;
                if(!level[y]&&edge[i].cost>0)
                {
                    level[y]=level[now]+1;
                    q.push(y);
                }
            }
        }
        return level[t]!=0;//汇点是否在层次图中
    }
    int dfs(int s,int cp)//在层次图中寻找增广路进行增广
    {
        int flow=0,temp;
        int t;
        if(s==end||cp==0)return cp;
        for(;t_head[s]+1;t_head[s]=edge[t_head[s]].next)
        {
            int y=edge[t_head[s]].to;
            if(level[s]+1==level[y])
            {
                temp=dfs(y,min(cp,edge[t_head[s]].cost));
                if(temp>0)
                {
                    edge[t_head[s]].cost-=temp;
                    edge[t_head[s]^1].cost+=temp;
                    flow+=temp;
                    cp-=temp;
                    if(cp==0)break;
                }
            }
        }
        return flow;
    }
    
    int dinic()
    {
        int ans=0,flow=0;
        while(bfs(start,end))//汇点不在层次图中、算法终止
        {
            for(int i=0;i<=end;i++)
                t_head[i]=head[i];
            ans+=dfs(start,INF);
        }
        return ans;
    }
    void add(int x,int y,int val)
    {
        edge[k].to=y;
        edge[k].cost=val;
        edge[k].next=head[x];
        head[x]=k++;
    
        edge[k].to=x;
        edge[k].cost=0;
        edge[k].next=head[y];
        head[y]=k++;
    }
    
    int main()
    {
        //freopen("C:\Users\终将我要华丽的逆袭\Desktop\lx_Zz_in.txt","r",stdin);
        //freopen("C:\Users\终将我要华丽的逆袭\Desktop\lx_Zz_out.txt","w",stdout);
    
    	int n,m;
    	scanf("%d%d",&n,&m);
    	init();
    	int x;
    	start=0;end=n+m+1;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&x);
    		add(start,i,x);
    	}
    	int sum=0;
    	for(int i=1;i<=m;i++)
    	{
    		int a,b,c;
    		scanf("%d%d%d",&a,&b,&c);
    		add(a,n+i,INF);
    		add(b,n+i,INF);
    		add(n+i,end,c);
    		sum+=c;
    	}
    	int ans=dinic();
    	printf("%d
    ",sum-ans);
        return 0;
    }

    非递归更高效的


    /* 题目: vijos 1352  */
    /* 作者: lx_Zz       */
    /* 时间: 2014.5.20   */
    #include<cstdio>
    #include<queue>
    #include<vector>
    #include<map>
    #include<string>
    #include<iostream>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int INF=0x7ffffff;
    const int MAXN=60005;//点数的最大值
    const int MAXM=500005;//边数的最大值
    
    
    struct Node
    {
        int from,to,next;
        int cap;
    }edge[MAXM];
    int tol;
    
    int dep[MAXN];//dep为点的层次
    int head[MAXN];
    
    int n;
    void init()
    {
        tol=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w)//第一条变下标必须为偶数
    {
        edge[tol].from=u;
        edge[tol].to=v;
        edge[tol].cap=w;
        edge[tol].next=head[u];
        head[u]=tol++;
        edge[tol].from=v;
        edge[tol].to=u;
        edge[tol].cap=0;
        edge[tol].next=head[v];
        head[v]=tol++;
    }
    
    int BFS(int start,int end)
    {
        int que[MAXN];
        int front,rear;
        front=rear=0;
        memset(dep,-1,sizeof(dep));
        que[rear++]=start;
        dep[start]=0;
        while(front!=rear)
        {
            int u=que[front++];
            if(front==MAXN)front=0;
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(edge[i].cap>0&&dep[v]==-1)
                {
                    dep[v]=dep[u]+1;
                    que[rear++]=v;
                    if(rear>=MAXN)rear=0;
                    if(v==end)return 1;
                }
            }
        }
        return 0;
    }
    int dinic(int start,int end)
    {
        int res=0;
        int top;
        int stack[MAXN];//stack为栈。存储当前增广路
        int cur[MAXN];//存储当前点的后继
        while(BFS(start,end))
        {
            memcpy(cur,head,sizeof(head));
            int u=start;
            top=0;
            while(1)
            {
                if(u==end)
                {
                    int min=INF;
                    int loc;
                    for(int i=0;i<top;i++)
                      if(min>edge[stack[i]].cap)
                      {
                          min=edge[stack[i]].cap;
                          loc=i;
                      }
                    for(int i=0;i<top;i++)
                    {
                        edge[stack[i]].cap-=min;
                        edge[stack[i]^1].cap+=min;
                    }
                    res+=min;
                    top=loc;
                    u=edge[stack[top]].from;
                }
                for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)
                  if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])
                     break;
                if(cur[u]!=-1)
                {
                    stack[top++]=cur[u];
                    u=edge[cur[u]].to;
                }
                else
                {
                    if(top==0)break;
                    dep[u]=-1;
                    u=edge[stack[--top]].from;
                }
            }
        }
        return res;
    }
    
    int main()
    {
        //freopen("C:\Users\终将我要华丽的逆袭\Desktop\lx_Zz_in.txt","r",stdin);
        //freopen("C:\Users\终将我要华丽的逆袭\Desktop\lx_Zz_out.txt","w",stdout);
    
    	int n,m;
    	int start,end;
    	scanf("%d%d",&n,&m);
    	init();
    	int x;
    	start=0;end=n+m+1;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&x);
    		add(start,i,x);
    	}
    	int sum=0;
    	for(int i=1;i<=m;i++)
    	{
    		int a,b,c;
    		scanf("%d%d%d",&a,&b,&c);
    		add(a,n+i,INF);
    		add(b,n+i,INF);
    		add(n+i,end,c);
    		sum+=c;
    	}
    	int ans=dinic(start,end);
    	printf("%d
    ",sum-ans);
        return 0;
    }


  • 相关阅读:
    扩展方法 之 Asp.Net篇【转】
    PowerDesiGner数据库设计
    DataFormatString格式化字符串的总结
    C#序列化对象为XMl于反序列化
    c# 反射初探【转】
    事件驱动的javascript 【转】
    每日一题力扣598
    每日一题力扣283
    每日一题力扣189数组的旋转 取模这个想法好棒!
    每日一题力扣119杨辉三角
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5156513.html
Copyright © 2011-2022 走看看