牛客国庆day 6 A

 题目链接 : https://ac.nowcoder.com/acm/contest/206/A

  这个题去年有幸去秦皇岛参加集训,见过这道题,当时特别菜还不会网络流,现在学了一点发现这个网络流还是比较简单的。

  首先题意要求价值根据蜡烛数量有变化,因为数据不大,我们可以每个点多联几条变,写成第一区域连接汇点

  区域到汇点的流量为1,费用为1,3,5,7.。。。。,因为从小到大加和,和正好为x的平方,所以的边流量都为1,因为只可以走一次,最后从原点到汇点跑个网络流就可以了

  AC代码 : 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<vector>
#include<queue>
using namespace std;
#define INT_MAX 0x73f3f3f
typedef struct w_w{
    int eend;
    int weight;
    int liu;
    int next;
}miao;
miao x[200010];
int head[200];
int cnt;
int money[200];
int bian[200];
int dian[200];
int vis[200];
queue<int> q1;
int spfa(int s,int e){
    memset(bian,-1,sizeof(bian));
    memset(dian,-1,sizeof(dian));
    for(int i=0;i<=199;i++){
        money[i]=INT_MAX;
    }
    money[e]=INT_MAX;
    while(q1.size()) q1.pop();
    q1.push(s);
    money[s]=0;
    while(q1.size()){
        int dang=q1.front();
        //printf("%d\n",dang);
        q1.pop();
        vis[dang]=0;
        for(int i=head[dang];i!=-1;i=x[i].next){
            int to=x[i].eend;
            int w=x[i].weight;
            if(x[i].liu>0&&money[dang]+w<money[to]){
                money[to]=money[dang]+w;
                if(vis[to]==0) q1.push(to);
                vis[to]=1;
                bian[to]=i;
                dian[to]=dang;
                //printf("%d %d %d\n",dang,i,to);
                //system("pause");
            }
        }
    }
    if(money[e]!=INT_MAX) return 1;
    else return 0;
}
void add(int s,int e,int l,int w){
    x[cnt].eend=e;
    x[cnt].weight=w;
    x[cnt].liu=l;
    x[cnt].next=head[s];
    head[s]=cnt++;
}
int main()
{
    int m,n;
    scanf("%d %d",&m,&n);
    memset(head,-1,sizeof(head));
    cnt=0;
    int start=0;
    int eend=199;
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d %d",&a,&b);
        add(0,n+i,1,0);
        add(n+i,0,0,0);
        add(n+i,a,1,0);
        add(a,n+i,0,0);
        add(n+i,b,1,0);
        add(b,n+i,0,0);
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<n+10;j++){
            add(i,eend,1,2*j+1);
            add(eend,i,0,0-(2*j+1));
        }
    }
    int sum=0;
    while(spfa(start,eend)){
        //printf("+++\n");
        int minn=INT_MAX;
        for(int i=eend;i!=start;i=dian[i]){
            int k=bian[i];
            //printf("+++%d\n",i);
            minn=min(minn,x[k].liu);
        }
        sum+=minn*money[eend];
        for(int i=eend;i!=start;i=dian[i]){
            int k=bian[i];
            x[k].liu-=minn;
            x[k^1].liu+=minn;
            //printf("%d\n",k);
        }
    }
    printf("%d\n",sum);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fzw1523/p/10799343.html