[HNOI2005]狡猾的商人

北城余情 提交于 2020-01-29 16:51:28

题目描述

输入输出格式

输入格式 

从文件input.txt中读入数据,文件第一行为一个正整数w,其中w < 100,表示有w组数据,即w个账本,需要你判断。每组数据的第一行为两个正整数n和m,其中n < 100,m < 1000,分别表示对应的账本记录了多少个月的收入情况以及偷看了多少次账本。接下来的m行表示刁姹偷看m次账本后记住的m条信息,每条信息占一行,有三个整数s,t和v,表示从第s个月到第t个月(包含第t个月)的总收入为v,这里假设s总是小于等于t。

输出格式:

输出文件output.txt中包含w行,每行是true或false,其中第i行为true当且仅当第i组数据,即第i个账本不是假的;第i行为false当且仅当第i组数据,即第i个账本是假的。

输入输出样例

输入样例#1:
2
3 3
1 2 10
1 3 -5
3 3 -15
5 3
1 5 100
3 5 50
1 2 51
输出样例#1:
true
false

 

题解:

1.差分约束,直接x-y连v的边,并且y-x连-v的边,然后spfa找负环

2.带权并查集,每一次合并find(y)和x并修改路径上的dis值,顺便路径压缩.然后如果在同一集合中直接判断矛盾即可

 

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 using namespace std;
 8 const int N=505;
 9 int fa[N],dis[N];
10 int find(int x){
11     if(x==fa[x])return x;
12     int t=find(fa[x]);
13     if(fa[x]!=fa[fa[x]])
14     dis[x]+=dis[fa[x]];
15     fa[x]=t;
16     return fa[x];
17 }
18 void work(){
19     int n,m,x,y,z,flag=0;
20     scanf("%d%d",&n,&m);
21     for(int i=1;i<=n+1;i++)fa[i]=i,dis[i]=0;
22     for(int i=1;i<=m;i++){
23         scanf("%d%d%d",&x,&y,&z);
24         y++;
25         if(find(x)==find(y)){
26             if(dis[y]-dis[x]!=z && !flag){
27                 printf("false\n");
28                 flag=1;
29             }
30         }
31         else
32             dis[find(y)]=z-dis[y],fa[find(y)]=x,find(y);
33     }
34     if(!flag)
35     printf("true\n");
36 }
37 int main()
38 {
39     freopen("sum.in","r",stdin);
40     freopen("sum.out","w",stdout);
41     int T;
42     scanf("%d",&T);
43     while(T--){
44         work();
45     }
46     return 0;
47 }
带权并查集

 

 1 #include <algorithm>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cmath>
 6 using namespace std;
 7 const int N=505,M=5005;
 8 int n,m,num=0,head[N];
 9 struct Lin{
10     int next,to,dis;
11 }a[M<<1];
12 void init(int x,int y,int z){
13     a[++num].next=head[x];a[num].to=y;a[num].dis=z;head[x]=num;
14 }
15 int q[N*10],f[N];bool vis[N];
16 bool check(int s){
17     int t=0,sum=1,x,u;q[1]=s;vis[s]=true;
18     while(t!=sum){
19         t++;x=q[t];
20         for(int i=head[x];i;i=a[i].next){
21             u=a[i].to;
22             if(!vis[u]){
23                 vis[u]=true;
24                 f[u]=f[x]+a[i].dis;
25                 q[++sum]=u;
26             }
27             else if(f[x]+a[i].dis!=f[u])return false;
28         }
29     }
30     return true;
31 }
32 void Clear(){
33     memset(f,0,sizeof(f));
34     memset(vis,0,sizeof(vis));
35     memset(head,0,sizeof(head));
36     num=0;
37 }
38 void work(){
39     Clear();
40     int x,y,z;
41     scanf("%d%d",&n,&m);
42     for(int i=1;i<=m;i++){
43         scanf("%d%d%d",&x,&y,&z);
44         init(x,y+1,z);init(y+1,x,-z);
45     }
46     bool fg=false;
47     for(int i=1;i<=n;i++){
48         if(vis[i])continue;
49         if(!check(i)){
50             fg=true;
51             break;
52         }
53     }
54     if(!fg)printf("true\n");
55     else printf("false\n");
56 }
57 int main()
58 {
59     freopen("sum.in","r",stdin);
60     freopen("sum.out","w",stdout);
61     int T;
62     scanf("%d",&T);
63     while(T--)
64         work();
65     return 0;
66 }
spfa乱搞

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!