NOIP 关押罪犯

(prison.pas/c/cpp)
【问题描述】
  S 城现有两座监狱,一共关押着 N 名罪犯,编号分别为 1~N。他们之间的关系自然也极
不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨
气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之
间的积怨越多。如果两名怨气值为 c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并
造成影响力为 c 的冲突事件。
每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,
然后上报到 S 城 Z 市长那里。公务繁忙的 Z 市长只会去看列表中的第一个事件的影响力,
如果影响很坏,他就会考虑撤换警察局长。
在详细考察了 N 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在
两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只
要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。那
么,应如何分配罪犯,才能使 Z 市长看到的那个冲突事件的影响力最小?这个最小值是多
少?
【输入】
输入文件名为 prison.in。输入文件的每行中两个数之间用一个空格隔开。
第一行为两个正整数 N 和 M,分别表示罪犯的数目以及存在仇恨的罪犯对数。
接下来的 M 行每行为三个正整数 aj, bj, cj,表示 aj 号和 bj 号罪犯之间存在仇恨,其怨
气值为 cj。数据保证1 ≤ a j < b j N , 0 < c j ≤ 1,000,000,000 ,且每对罪犯组合只出现一
次。
【输出】
输出文件 prison.out 共 1 行,为 Z 市长看到的那个冲突事件的影响力。如果本年内监狱
中未发生任何冲突事件,请输出 0。
【输入输出样例】
prison.in prison.out
4 6
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884
3512

【数据范围】
对于 30%的数据有 N ≤ 15。
对于 70%的数据有 N ≤ 2000, M ≤ 50000。
对于 100%的数据有 N ≤ 20000, M ≤ 100000。

分析:

  明显的二分答案,但是写判断函数时一定要用二分图染色,我一开始想的是用vis[]数组表示,vis[i]==0时说明i犯人待分配,vis[i]==1说明i犯人分配到集合1,vis[i]==2说明i犯人分配到集合2,然后搞好几个判断,但是这样错误很明显,假设 ①与②分别分到监狱一和二,④和③分别分到监狱一和二,这时如果②和③不能分到一起,判断就会return false,但是其实可以①③一起,②④一起。。。

  下面这个是错的:

 //错的错的错的  才20分 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 using namespace std;
 8 typedef long long LL;
 9 LL N,M;
10 struct node{
11     LL a,b,c;
12 };
13 node pris[1000000];
14 LL cmp(const node &q,const node &w){
15     if(q.c<w.c) return 1;
16     return 0;
17 }
18 LL find(LL,LL);
19 bool jud(LL);
20 int main(){
21     freopen("prison.in","r",stdin);
22     freopen("prison.out","w",stdout);
23     scanf("%lld%lld",&N,&M);
24     for(LL i=1;i<=M;i++)
25         scanf("%lld%lld%lld",&pris[i].a,&pris[i].b,&pris[i].c);
26     sort(pris+1,pris+M+1,cmp);
27     if(jud(0)==true){
28         cout<<0;
29         return 0;
30     }
31     cout<<find(pris[1].c,pris[M].c);
32     return 0;
33 }
34 LL find(LL l,LL r){
35     if(r-l<=1){
36         if(jud(l)==true) return l;
37         else return r;
38     }
39     LL mid=(l+r)>>1;
40     if(jud(mid)==true){
41         find(l,mid);
42     }
43     else{
44         find(mid+1,r);
45     }
46 }
47 bool jud(LL x){
48     LL vis[200000];
49     memset(vis,0,sizeof(vis));
50     for(LL i=1;i<=M;i++){
51         LL u=pris[i].a;
52         LL v=pris[i].b;
53         if(pris[i].c>x){//可能会有冲突
54             if(vis[u]==0&&vis[v]==0){//没有确定集合
55                 vis[u]=1;
56                 vis[v]=2;
57             }
58             else{
59                 if(vis[u]!=0&&vis[v]!=0&&vis[u]==vis[v]) return false;//必然爆发冲突
60                 else{
61                     if(vis[u]!=0&&vis[v]==0){
62                         if(vis[u]==1) vis[v]=2;
63                         else if(vis[u]==2) vis[v]=1;
64                     }
65                     else if(vis[u]==0&&vis[v]!=0){
66                         if(vis[v]==1) vis[u]=2;
67                         else if(vis[v]==2) vis[u]=1;
68                     }
69                 }
70             }
71         }
72     }
73
74     return true;
75 }

  正解是二分图染色,由于有20000个点,所以应该用vector,不过因为图不是太稠密,所以开to[20001][500]也能过。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<vector>
 8 #include<queue>
 9 using namespace std;
10 typedef long long LL;
11 LL N,M;
12 struct node{
13     LL a,b,c;
14 };
15 node pris[100005];
16 LL cmp(const node &q,const node &w){
17     if(q.c<w.c) return 1;
18     return 0;
19 }
20 LL to[20001][500];
21 LL vis[100005];
22 LL find(LL,LL);
23 bool jud(LL);
24 bool color(LL);
25 int main(){
26     freopen("prison.in","r",stdin);
27     freopen("prison.out","w",stdout);
28     scanf("%lld%lld",&N,&M);
29     for(LL i=1;i<=M;i++)
30         scanf("%lld%lld%lld",&pris[i].a,&pris[i].b,&pris[i].c);
31     sort(pris+1,pris+M+1,cmp);
32     if(jud(0)==true){
33         cout<<0;
34         return 0;
35     }
36     cout<<find(pris[1].c,pris[M].c);
37     return 0;
38 }
39 LL find(LL l,LL r){
40     if(r-l<=1){
41         if(jud(l)==true) return l;
42         else return r;
43     }
44     LL mid=(l+r)>>1;
45     if(jud(mid)==true){
46         find(l,mid);
47     }
48     else{
49         find(mid+1,r);
50     }
51 }
52 bool jud(LL x){
53     memset(vis,0,sizeof(vis));
54     memset(to,0,sizeof(to));
55     for(LL i=1;i<=M;i++){
56         LL u=pris[i].a;
57         LL v=pris[i].b;
58         if(pris[i].c>x){
59             to[u][0]++;
60             to[v][0]++;
61             to[u][to[u][0]]=v;
62             to[v][to[v][0]]=u;
63         }
64     }
65     for(LL i=1;i<=N;i++){
66         if(vis[i]==0&&to[i][0]>0){
67             if(color(i)==false) return false;
68         }
69     }
70     return true;
71 }
72 bool color(LL root){
73     vis[root]=1;
74     static queue<LL> Q;
75     while(Q.size()>0) Q.pop();
76     Q.push(root);
77     while(Q.size()>0){
78         int x=Q.front();
79         Q.pop();
80         for(int i=1;i<=to[x][0];i++){
81             int y=to[x][i];
82             if(vis[y]==0){
83                 if(vis[x]==1) vis[y]=2;
84                 else vis[y]=1;
85                 Q.push(y);
86             }
87             else if(vis[y]==vis[x]) return false;
88         }
89     }
90     return true;
91 }
时间: 2024-08-26 02:13:36

NOIP 关押罪犯的相关文章

10 noip 关押罪犯 解题报告

题目描述 Description S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极 不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨 气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之 间的积怨越多.如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并 造成影响力为c 的冲突事件. 每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表, 然后上报到S 城Z 市长那

贪心 + 并查集 之 CODE[VS] 1069 关押罪犯 2010年NOIP全国联赛提高组

/* 贪心 + 并查集 之 CODE[VS] 1069 关押罪犯  2010年NOIP全国联赛提高组 两座监狱,M组罪犯冲突,目标:第一个冲突事件的影响力最小. 依据冲突大小,将M组罪犯按从大到小排序,按照排序结果,依次把每组罪犯分开放入两个监狱, 直到当前这组罪犯已经在同一个监狱中了,此时即为答案. 实现: 1)通过不在同一个监狱的罪犯,推断出在同一个监狱的罪犯.(依据:一共就两个监狱)      ftr[b] = a+n   // a和b是在不同监狱 ftr[c] = a+n   // a和

洛谷 P1525 关押罪犯==codevs 1069 关押罪犯[NOIP 2010]

P1525 关押罪犯 513通过 1.4K提交 题目提供者该用户不存在 标签图论并查集NOIp提高组2010 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 咳咳.竟MLE了. 囧.运行时错误,错误编号-… 点2是何方神圣? 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多.

Vijos P1776关押罪犯

题目来源:https://www.vijos.org/p/1776 P1776关押罪犯 Accepted 标签:NOIP提高组2010[显示标签] 描述 S城现有两座监狱,一共关押着N名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多.如果两名怨气值为c的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c的冲

codevs 1069关押罪犯

传送门 1069 关押罪犯 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamon 题目描述 Description S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极 不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨 气值"(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之 间的积怨越多.如果两名怨气值为c 的罪犯被关押在同一监狱,他

1069 关押罪犯

codevs——1069 关押罪犯 洛谷——P1525 关押罪犯 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极 不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨 气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之 间的积怨越多.如果两名怨

NOIP2010提高组 关押罪犯 -SilverN

(洛谷P1525) 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多.如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件. 每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里.公务繁忙的

NOIP2010 提高组 洛谷P1525 关押罪犯

刚才做并查集想到了这道以前做的题,干脆一并放上来 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多.如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件. 每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到

tyvj P1403 关押罪犯 题解

P1403 [NOIP2010]关押罪犯 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时 可能爆发冲突.我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多.如果两名怨气值为c 的罪犯 被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件.    每年