BZOJ2095 bridge

来源:互联网 发布:mac os 10.13iso镜像 编辑:程序博客网 时间:2024/06/08 01:17

题意:
给出一个n个点m条边的无向图,每个边有一正一反两个权值;
现要从点1出发,对每条边经过且仅经过一次;
求一种方案使经过的最大权值最小;

输入:第一行为两个用空格隔开的整数n(2<=n<=1000),m(1<=m<=2000),接下来读入m行由空格隔开的4个整数a,b(1<=a,b<=n,a<>b),c,d(1<=c,d<=1000)

最大权值最小,可以二分转换为判定性问题。
这样问题就转换成了,判断是不是欧拉回路的一个问题。limit重建图。但这样问题是,图变成了一个混合图,其中有有向边也有无向边。
有向图欧拉回路:每个点indegree==outdegree
有向图欧拉回路:至多两个点的度数绝对值差1,且一个出度多、一个入度多。
无向图欧拉回路:每个点度数为偶数
无向图欧拉路:至多2个点度数为奇数。

混合图怎么办呢。。我们可以转化为有向图来做。
1.给无向边定向。
2.图不一定是个欧拉回路,我们发现把一个无向边反向,影响的度数总是±2的。所以如果出入度之差是奇数,一定不是欧拉回路。
3.每个点val=indegree-outdgree,为了维护流量平衡,把val>0的点连S,val<0的点连T,容量都为val/2.
无向边,按照定向的方向反向建边,容量1。
跑最大流看满不满流,很像无源汇有上下界可行流的做法qwq。

#include<bits/stdc++.h>using namespace std;const int MAXN=1e4+5;const int INF=1e9+7;struct edge{    int to,next,w;}e[MAXN<<2];struct data{    int u,v;}jilu[MAXN<<2];int n,m,s,t;int head[MAXN],cur[MAXN],cnt=1;inline void add(int u,int v,int w){    e[++cnt]=(edge){v,head[u],w},head[u]=cnt;    e[++cnt]=(edge){u,head[v],0},head[v]=cnt;}int dep[MAXN];queue<int>q;bool bfs(int x){    memset(dep,0,sizeof(dep));    q.push(x);dep[x]=1;    while(q.size()){        int u=q.front();q.pop();        for(int i=head[u];i;i=e[i].next){            int v=e[i].to,w=e[i].w;            if(!dep[v]&&w){                dep[v]=dep[u]+1;                q.push(v);            }        }    }    if(!dep[t])return 0;    return 1; }int dfs(int u,int flow){    if(u==t||flow==0)return flow;    for(int &i=cur[u];i;i=e[i].next){        int v=e[i].to,w=e[i].w;        if(dep[v]==dep[u]+1&&w){            int tem=dfs(v,min(w,flow));            if(tem){                e[i].w-=tem;e[i^1].w+=tem;                return tem;            }        }    }    return 0;}int dinic(){    int ans=0;    while(bfs(s)){        for(int i=s;i<=t;i++)cur[i]=head[i];        while(int d=dfs(s,INF))ans+=d;    }    return ans;}int u[MAXN],v[MAXN],w1[MAXN],w2[MAXN],in[MAXN],out[MAXN],num;bool judge(int lm){    num=0;    for(int i=1;i<=m;i++){        if(w1[i]<=lm)out[u[i]]++,in[v[i]]++;        if(w2[i]<=lm)add(v[i],u[i],1);    }    for(int i=1;i<=n;i++){        in[i]=in[i]-out[i];        if(abs(in[i])&1)return 0;        if(in[i]>0)add(s,i,in[i]/2),num+=in[i]/2;        else if(in[i]<0)add(i,t,-in[i]/2);    }    if(dinic()==num)return 1;    return 0;}void mem(){    memset(e,0,sizeof(e));    memset(head,0,sizeof(head));    memset(in,0,sizeof(in));    memset(out,0,sizeof(out));    cnt=1;}int minn=INF,maxx=-INF;int main(){    scanf("%d%d",&n,&m);    s=0,t=n+1;    for(int i=1;i<=m;i++){        scanf("%d%d%d%d",&u[i],&v[i],&w1[i],&w2[i]);        if(w1[i]>w2[i])swap(w1[i],w2[i]),swap(u[i],v[i]);        minn=min(minn,min(w1[i],w2[i]));        maxx=max(maxx,max(w1[i],w2[i]));    }    int l=minn,r=maxx;    while(l<=r){        mem();        int mid=(l+r)>>1;        if(judge(mid))r=mid-1;        else l=mid+1;    }    mem();    if(judge(l))printf("%d\n",l);    else printf("NIE\n");    return 0;}
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 买房买几层好 刚买的二手房可以卖吗 买新房网站 新房买了多久可以卖 如何买二手房 买二手房注意 99年的二手房能买吗 买新房子要交哪些税 十种户型房子不能买 买房子要交哪些税 买房子要注意什么细节 梦到买房子 买碧桂园房子要注意 买房子贷款流程 房子买在大连好后悔 买房子需要准备什么 看房子哪个网站好 买房子要注意什么手续 看房子需要注意什么 买房子哪个软件好 买房子注意什么 买房子都需要什么 买什么样的房子好 网上买房子哪个网站好 看房子的软件 买房子需要注意什么问题 买房子哪个网站好 多少岁可以买房子 买哪里的房子好 后悔在泉州买房子了 买房子的人 房子多久可以卖 买房子价格 卖买房子 购买房子需要注意哪些问题 房子怎么买 买卖房子的网站 三亚房子值得买吗 购买房子的流程 装修房子平方怎么算 15年的房子还值得买吗