zoukankan      html  css  js  c++  java
  • 【Halum操作-UVA 11478】

    ·英文题,述大意:
          输入有向图一个(什么边的端点啊,边权啊)。每次可以选择一个节点和一个整数,然后把这个结点的出边边权加上该整数,入边边权减去该整数,目标:使得所有边的最小值非负且尽量大。

    ·分析:

          修改结点周围的边权,题目中既没有限制次数,也没有规定在意先后顺序,这启示我们,每一个操作的效果是可以叠加的(同时就不分先后),所以可以将题目简化为:每一个节点只用一个整数操作一次。

          差分约束的思想运用:如果我们设num(u)表示给节点u施加的那个整数值。则对于有向边(u,v)(权值为W),那么最终该边的边权为:

            W'=W+num(u)-num(v)

    读题目最后一句话,可以体会到这是一个美妙的二分。如果当前二分的值是X,表示最小边权。那么对于每一条边,都满足这个式子:

            W+num(u)-num(v)>=X

    =>   num(v)-num(u)<=W-X

    由于W-X在此时为定值,设P=W-X那么这些不等式都可以统一描述为:左边小于等于右边,左边两个节点信息之差,右边是一个定值。

    扭一扭,泡一泡:那么原式为:num(v)<=num(u)+P

    ·然后这和最短路的if()中的东西是一样的,所以用这些元素依葫芦画瓢地建图(奥,这道题是帮你建好了的……)如果当前二分的X不符合条件,会出现什么情况————出现负环。

    ·为什么是出现负环就代表不能使所有不等式同时成立呢?

    举例说明:(考虑一种建图状态)

    image

    如果将①③式相加,则会又得到一个关于b,c的不等式:

       sum(c)-sum(b)>=7

    该式子不幸地与②式矛盾。

    总结归纳地说:只要一坨”连连不等式”(即图中一个环)右边的数值加起来的和为负数(这不是说每个值都是负数),那么对于任意其中点对{m,n},在原有的一个关于它们的不等式的基础上,可以通过其他等式相加再构造一个关于它俩的不等式中,必存在至少一组矛盾(一正一负,绝对爆炸)。所以负环就是不等式组不成立的直接表现。

    ·最后一个小提醒:在进行SPFA之前,该选谁作为起点呢?反正大家都是平等的,就一同压入队列吧。

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #include<queue>
     4 #include<cstring>
     5 #define go(i,a,b) for(int i=a;i<=b;i++)
     6 #define fo(i,a,x) for(int i=a[x],v=e[i].v;~i;i=e[i].next,v=e[i].v)
     7 #define inf 1000000000
     8 #define mem(a,b) memset(a,b,sizeof(a))
     9 using namespace std;const int N=503;struct E{int v,next,w;}e[N*80]; 
    10 int n,m,head[N],k,max_W=-inf,ans,d[N],update_times[N];
    11 void ADD(int u,int v,int w){e[k]=(E){v,head[u],w};head[u]=k++;}
    12 bool SPFA(int x)
    13 {
    14     queue<int>q;bool inq[N]={0};
    15     go(i,1,n)d[i]=update_times[i]=0,q.push(i),inq[i]=1;
    16     
    17     while(!q.empty()){int u=q.front();q.pop();inq[u]=0;
    18     fo(i,head,u)if(d[u]+e[i].w-x<d[v]){d[v]=d[u]+e[i].w-x;
    19         if(!inq[v]){q.push(v);inq[v]=1;
    20         if(++update_times[v]>n+1)return 0;}}}return 1;
    21 }
    22 int main(){while(~scanf("%d%d",&n,&m))
    23 {
    24     mem(head,-1);k=0;ans=-1;
    25     go(i,1,m){int u,v,w;scanf("%d%d%d",&u,&v,&w);
    26     max_W=max(max_W,w);ADD(u,v,w);}
    27     
    28     int l=1,r=max_W+1,mid;
    29     while(l<=r)mid=l+r>>1,SPFA(mid)?ans=mid,l=mid+1:r=mid-1;
    30         
    31     if(ans==max_W+1){printf("Infinite
    ");continue;}
    32     if(ans==-1){printf("No Solution
    ");continue;}
    33     printf("%d
    ",ans);
    34 }return 0;}//Paul_Guderian

    已经忘了回去的道路,走入独自一人的碎梦。————汪峰《碎梦》

  • 相关阅读:
    发送邮件
    php防止表单重复提交
    mysql 优化之注意
    mysqldump
    项目中下拉框链接问题
    css在IE和Firefox下的兼容性
    利用curl并发来提高页面访问速度
    修改linux下mysql目录权限
    ajax跨域
    wireshark抓包
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/6821557.html
Copyright © 2011-2022 走看看