zoukankan      html  css  js  c++  java
  • HAOI2015PG图

    P1857 - 【HAOI2015】PG图

    Description

    背景
    LDN不知道为什么特别喜欢PG,也许是某种原因吧……
    有一天,他发明了一个游戏“PG图”。
    问题描述

    给定一个有向图,每条边都有一个权值。
    每次你可以选择一个节点u和一个整数d,把所有以u为终点的边的权值减小d,把所有以u为起点的边的权值加上d。最后要让所有边的权值的最小值为正且尽量大。

    Input

    输入包含若干组数据。
    每组数据第一行为两个整数n和m(n<=500,m<=2700),表示点和边的个数。
    以下m行,每行包括3个整数u,v,w,表示u -> v有一条边权为w的边。(1<= u,v<= n, -10000<= w<= 10000)

    Output

    对于每组数据,输出边权最小值的最大值;
    如果无法让所有边权都大于0,输出“No Solution”;
    如果边权最小值可以无限大,输出“Infinite”。

    Sample Input

    2 1
    1 2 10
    2 1
    1 2 -10
    3 3
    1 2 4
    2 3 2
    3 1 5
    4 5
    2 3 4
    4 2 5
    3 4 2
    3 1 0
    1 2 -1

    Sample Output

    Infinite
    Infinite
    3
    1

    Hint

    数据范围与约定

    对于30%的数据:2<= n<= 10,1<= m<= 100
    对于60%的数据:2<= n<= 100,1<= m<=1000
    对于100%的数据:2<= n<= 500,1<= m<=2700

    Source

    图论 , 差分约束

     
    通过设每个点的d值为未知数,由于是最小值最大,所以可以用二分,写出式子(a -> b) 

    W+sum(a)-sum(b)>=mid sum(b)-sum(a)<=W-mid;因此就可以用差分约束来写;

    想一下,如果mid可行,那么答案上移,不行,下移,判断行不行,也就是spfa能否跑出来,就是看是否存在负权环,可以用递归版的spfa :

    bool spfa(int x) {
        vis[x]=1;
        for(int i=head[x];i;i=e[i].net) {
            int to=e[i].to;
            if(dis[to]>dis[x]+e[i].w) {
                if(vis[to]) return 1;
                dis[to]=dis[x]+e[i].w;
                if(spfa(to)) return 1;
            }
        }
        return vis[x]=0;
    }
    

      

    如果max(r+1)都可以,那么解就是正无穷;1不行,那么无解;

    收获 : 首先想到的一定是二分答案,所以不要想d值怎么确定,最后的答案是多少,先设出来,得到一个式子(a -> b) W+sum(a)-sum(b)>=mid ;就很显然用差分约束了;

    一定要学会分析,不要急着确定每个d,先列式子,一般是差分约束;

     1 /* QYP kuai wo dai ma*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<iomanip>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<ctime>
    10 #include<cmath>
    11 #include<stack>
    12 #include<map>
    13 #include<set>
    14 #define rep(i,a,b) for(register int i=a;i<=b;i++)
    15 #define ll long long
    16 #define re register
    17 using namespace std;
    18 const int N=510,M=2710;
    19 struct Edge{
    20     int to,net,w;
    21 }e[M];
    22 int head[N],n,m,num_e;
    23 int dis[N];
    24 inline int gi() {
    25     re int res=0,f=1;
    26     char ch=getchar();
    27     while((ch<'0'||ch>'9')&&(ch!='-')) ch=getchar();
    28     if(ch=='-') ch=getchar(),f=-1;
    29     while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar();
    30     return res*f;
    31 }
    32 inline void add(int x,int y,int w) {
    33     e[++num_e].to=y,e[num_e].w=w,e[num_e].net=head[x],head[x]=num_e;
    34 }
    35 bool vis[N];
    36 bool spfa(int x) {
    37     vis[x]=1;
    38     for(int i=head[x];i;i=e[i].net) {
    39         int to=e[i].to;
    40         if(dis[to]>dis[x]+e[i].w) {
    41             if(vis[to]) return 1;
    42             dis[to]=dis[x]+e[i].w;
    43             if(spfa(to)) return 1;
    44         }
    45     }
    46     return vis[x]=0;
    47 }
    48 inline bool check(int x) {
    49     rep(u,1,n)
    50         for(int i=head[u];i;i=e[i].net) e[i].w-=x;
    51     bool flag=1;
    52     rep(i,1,n) {
    53         memset(dis,0,sizeof(dis));
    54         memset(vis,0,sizeof(vis));
    55         if(spfa(i)) {flag=0;break;}
    56     }
    57     rep(u,1,n)
    58         for(int i=head[u];i;i=e[i].net) e[i].w+=x;
    59     return flag;
    60 }
    61 int main() {
    62     freopen("pg.in","r",stdin);
    63     freopen("pg.out","w",stdout);
    64     while(scanf("%d%d",&n,&m)!=EOF) {
    65         memset(head,0,sizeof(head)),num_e=0;
    66         int l=0,r;
    67         rep(i,1,m) {
    68             re int u=gi(),v=gi(),w=gi();
    69             add(u,v,w);
    70             r=max(w,r);
    71         }
    72         if(!check(1)) {puts("No Solution");continue;}
    73         else if(check(r+1)) {puts("Infinite");continue;}
    74         re int mid=0;
    75         while(l<=r) {
    76             mid=(l+r)>>1;
    77             if(check(mid)) l=mid+1;
    78             else r=mid-1;
    79         }
    80         printf("%d
    ",r);
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    SolidWorks 2-12 拉伸特征03
    css记
    微信小程序的wxss好难啊,记录我的搞笑界面
    redis的学习使用,第二章
    本周学习Task-Rocketmq
    springcloud-ribbon的使用
    eclipse上使用svn更新代码
    新入职感觉
    在windows里面的数据库里面存emoji表情
    centos7,关闭mysql。出现mysql启动不了的情况
  • 原文地址:https://www.cnblogs.com/ypz999/p/6818794.html
Copyright © 2011-2022 走看看