• UVA 11478 Halum(差分约束)


    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34651

    【思路】

           差分约束系统。

           设结点u上的操作和为sum[u],则边(u,v)权值为d-sum[v]+sum[u]。对于最小值最大问题我们想到二分答案,设二分值为x,则问题变为判断最小值为x时题目是否存在解。对于权值我们有不等式d-sum[v]+sum[u]>=x  =>  sum[v]<=sum[u]+(d-x),由此可以建立差分约束系统。

           无解:如果最小值为1时依然不成立。

           任意解:如果最小值为R+1时成立。

           否则二分答案取最大值,当图中有负权环时差分约束系统无解即二分答案不成立。

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #include<queue>
     5 using namespace std;
     6 
     7 const int maxn = 1000+10;
     8 
     9 int n,m;
    10 struct Edge { int u,v,w;
    11 };
    12 vector<int> G[maxn];
    13 vector<Edge> es;
    14 void addedge(int u,int v,int w) {
    15     es.push_back((Edge){u,v,w});
    16     int m=es.size();  G[u].push_back(m-1);
    17 }
    18 bool spfa() {
    19     queue<int> q;
    20     int inq[maxn],d[maxn],cnt[maxn];
    21     memset(inq,0,sizeof(inq));
    22     memset(cnt,0,sizeof(cnt));
    23     for(int i=1;i<=n;i++)
    24         d[i]=0 , inq[i]=1 , q.push(i);
    25     while(!q.empty()) {
    26         int u=q.front(); q.pop(); inq[u]=0;
    27         for(int i=0;i<G[u].size();i++) {
    28             Edge e=es[G[u][i]];
    29             int v=e.v;
    30             if(d[v]>d[u]+e.w) {
    31                 d[v]=d[u]+e.w;
    32                 if(!inq[v]) {
    33                     inq[v]=1 , q.push(v);
    34                     if(++cnt[v]>(n)) return false;
    35                 }
    36             }
    37         }
    38     }
    39     return true;
    40 }
    41 bool can(int x) {
    42     for(int i=0;i<es.size();i++) es[i].w-=x;
    43     bool ans=spfa();
    44     for(int i=0;i<es.size();i++) es[i].w+=x;
    45     return ans;
    46 }
    47 
    48 int main() {
    49     while(scanf("%d%d",&n,&m)==2) {
    50         es.clear();
    51         for(int i=1;i<=n;i++) G[i].clear();
    52         int u,v,w;
    53         int L=0,R=0;
    54         for(int i=0;i<m;i++) {
    55             scanf("%d%d%d",&u,&v,&w);
    56             addedge(u,v,w); R=max(R,w);
    57         }
    58         if(can(R+1)) printf("Infinite
    ");
    59         else if(!can(1)) printf("No Solution
    ");
    60         else {
    61             while(L<R) {
    62                 int M=L+(R-L+1)/2;
    63                 if(can(M)) L=M; else R=M-1;
    64             }
    65             printf("%d
    ",L);
    66         }
    67     }
    68     return 0;
    69 }
  • 相关阅读:
    高并发网络编程之epoll详解
    位操作实现加减乘除四则运算
    堆和栈的区别
    IT思想类智力题
    C/C++基础总结
    数据库总结
    面试网络总结
    Windows内存管理和linux内存管理
    面试操作系统总结
    数据结构与算法
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5095790.html
Copyright © 2020-2023  润新知