• [BZOJ2330][SCOI2011]糖果 差分约束系统+最短路


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2330

    类似于题目中这种含有不等式关系,我们可以建立差分约束系统来跑最长路或最短路。

    对于一个不等式$X_1-X_2>=a$我们可以看成是$X_1>=X_2+a$,把$X_1$和$X_2$看成两个点,我们可以发现这个关系跟最长路中的$dis[v]>=dis[u]+w[i]$很像,就是最长路中的点一定满足这样的关系。

    所以我们就按着这个思路,先把关于点$X_1$,$X_2$和边$a$的图建好,再来跑一遍最长路,如果有解,就一定满足题目中的不等式关系。

    具体连边方式就是若有$a>=b+c$,则连$b$到$a$,边权为$c$。最短路同理。

    最长路无解的情况就是存在正权环,最短路存在负权环。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 using namespace std;
     6 typedef long long ll;
     7 const int INF=1<<30;
     8 int inline readint(){
     9     int Num;char ch;
    10     while((ch=getchar())<'0'||ch>'9');Num=ch-'0';
    11     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
    12     return Num;
    13 }
    14 int N,K;
    15 int to[300010],ne[300010],w[300010],fir[100010],cnt=0;
    16 void Add(int a,int b,int c){
    17     to[++cnt]=b;
    18     w[cnt]=c;
    19     ne[cnt]=fir[a];
    20     fir[a]=cnt;
    21 }
    22 int vis[100010],dis[100010];
    23 bool in[100010];
    24 queue <int> q;
    25 ll spfa(){
    26     for(int i=1;i<=N;i++) dis[i]=-INF;
    27     in[N+1]=true;
    28     q.push(N+1);
    29     dis[N+1]=0;
    30     vis[N+1]=1;
    31     int u;
    32     while(!q.empty()){
    33         u=q.front();
    34         q.pop();
    35         in[u]=false;
    36         for(int i=fir[u];i!=-1;i=ne[i]){
    37             int v=to[i];
    38             if(dis[v]<dis[u]+w[i]){
    39                 dis[v]=dis[u]+w[i];
    40                 if(!in[v]){
    41                     q.push(v);
    42                     in[v]=true;
    43                     vis[v]++;
    44                     if(vis[v]>N) return -1;
    45                 }
    46             }
    47         }
    48     }
    49     ll ans=0;
    50     for(int i=1;i<=N;i++) ans+=dis[i];
    51     return ans; 
    52 }
    53 int main(){
    54     memset(fir,-1,sizeof(fir));
    55     N=readint();
    56     K=readint();
    57     for(int i=1;i<=K;i++){
    58         int X=readint(),
    59             A=readint(),
    60             B=readint();
    61         switch(X){
    62             case 1:
    63                 Add(B,A,0);
    64                 Add(A,B,0);
    65                 break;
    66             case 2:
    67                 if(A==B){
    68                     puts("-1");
    69                     return 0;
    70                 }
    71                 Add(A,B,1);
    72                 break;
    73             case 3:
    74                 Add(B,A,0);
    75                 break;
    76             case 4:
    77                 if(A==B){
    78                     puts("-1");
    79                     return 0;
    80                 }
    81                 Add(B,A,1);
    82                 break;
    83             case 5:
    84                 Add(A,B,0);
    85                 break;
    86         }
    87     }
    88     for(int i=N;i>=1;i--) Add(N+1,i,1);
    89     printf("%lld
    ",spfa());
    90     return 0;
    91 }
  • 相关阅读:
    输出由“*”组成的菱形
    一个简单的计算器(c++)
    输入学号,显示对应的姓名(c++)
    使用 Puppet 在 Windows Azure 中配备 Linux 和 Windows 环境
    微软开放技术发布针对 Mac 和 Linux 的更新版 Azure Node.JS SDK 和命令行工具
    微软开放技术开发了适用于 Windows Azure 移动服务的开源 Android SDK
    微软开放技术发布开源 Jenkins 插件以将 Windows Azure Blob 服务用的开作存储库
    VM Depot 登陆中国!
    VM Depot 喜迎中国本土开源镜像!
    VM Depot 助您使用本地开源软件架设开发 Web 站点
  • 原文地址:https://www.cnblogs.com/halfrot/p/7624245.html
Copyright © 2020-2023  润新知