zoukankan      html  css  js  c++  java
  • 省选模拟赛 project

    solution:
    最小割问题。
    建如下边:
    (S,i,Ai)代表选用A语言编写第i个项目;
    (i,T,Bi)代表选用A语言编写第i个项目;
    其后注意要反向连边
    (i,j,D)代表选用B语言编写第i个项目,选用A语言编写第j个项目;
    (j,i,C)代表选用A语言编写第i个项目,选用B语言编写第j个项目;

    litc学长出的题,引文最小割题目做的少,想的少,考试时一直没写出来,按题解自己写了个ISAP,已通过所有测试点。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    int n,m,S,T,A,B,ecnt,first[600000];
    struct Edge{int u,v,nxt,cap,flow;}e[1050000];
    bool vis[600000];
    int q[600000],d[600000],p[600000],num[600000],cur[600000];
    void Link(int u,int v,ll w)
    {
         e[++ecnt].u=u,e[ecnt].v=v,e[ecnt].cap=w,e[ecnt].flow=0;
         e[ecnt].nxt=first[u],first[u]=ecnt;
         e[++ecnt].u=v,e[ecnt].v=u,e[ecnt].cap=0,e[ecnt].flow=0;
         e[ecnt].nxt=first[v],first[v]=ecnt;
    }
    void bfs()
    {
         int head=0,tail=1;
         memset(vis,false,sizeof(vis));
         q[0]=T,d[T]=0,vis[T]=true;
         while(head^tail){
               int now=q[head++];
               for(int i=first[now];i;i=e[i].nxt)
                   if(!vis[e[i].u]&&e[i].cap>e[i].flow){
                       vis[e[i].u]=true;
                       d[e[i].u]=d[now]+1;
                       q[tail++]=e[i].u;
                   }
         }
    }
    int Agument()
    {
        int x=T,a=0x7fffffff;
        while(x^S){
              a=min(a,e[p[x]].cap-e[p[x]].flow);
              x=e[p[x]].u;
        }
        x=T;
        while(x^S){
              e[p[x]].flow+=(ll)a;
              e[p[x]^1].flow-=(ll)a;
              x=e[p[x]].u;
        }
        return a;
    }
    ll ISAP()
    {
        int x=S;
        ll flow=0;
        bfs();
        memset(num,0,sizeof(num));
        for(int i=S;i<=T;i++)
            num[d[i]]++,cur[i]=first[i];
        while(d[S]<n+1){
              if(!(x^T)){
                 flow+=(ll)Agument();
                 x=S;
              }
              bool advanced=false;
              for(int i=cur[x];i;i=e[i].nxt)
                  if(e[i].cap>e[i].flow&&d[x]==d[e[i].v]+1){
                     advanced=true;
                     cur[x]=p[e[i].v]=i;
                     x=e[i].v;
                     break;
                  }
              if(!advanced){
                 int mn=n;
                 for(int i=first[x];i;i=e[i].nxt)
                     if(e[i].cap>e[i].flow)
                        mn=min(mn,d[e[i].v]);
                 if(--num[d[x]]==0)break;
                 num[d[x]=mn+1]++;
                 cur[x]=first[x];
                 if(x^S)x=e[p[x]].u;
              }
        }
        return flow;
    }
    int main()
    {
        freopen("project.in","r",stdin);
        freopen("project.out","w",stdout);
        scanf("%d%d",&n,&m);
        S=0,T=n+1,ecnt=1;
        for(int i=1;i<=n;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                Link(S,i,x);
                Link(i,T,y);
        }
        for(int i=1;i<=m;i++){
                int x,y,c,d;
                scanf("%d%d%d%d",&x,&y,&c,&d);
                Link(x,y,d);
                Link(y,x,c);
        }
        printf("%I64d
    ",ISAP());//output 'min cut';
        fclose(stdin);fclose(stdout);
        return 0;
    }
    



  • 相关阅读:
    字符串hash
    堆优化的最短路
    unordered_map 的火车头
    扩展欧几里得求ax+by=c的最小正整数解
    欧拉筛
    Codeforces Round 649 (Rated for Div. 2)D. Ehab s Last Corollary (图论+简单环)
    牛客SQL题解-找出所有员工具体的薪水salary情况
    牛客SQL题解-查找薪水变动超过15次的员工号emp_no以及其对应的变动次数t
    牛客SQL题解-查找所有已经分配部门的员工的last_name和first_name以及dept_no,也包括暂时没有分配具体部门的员工
    牛客SQL题解- 查找所有已经分配部门的员工的last_name和first_name
  • 原文地址:https://www.cnblogs.com/keshuqi/p/5957743.html
Copyright © 2011-2022 走看看