S城现有两座监狱,一共关押着N名罪犯,编号分别为1~N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为c的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c的冲突事件。每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S城Z市长那里。公务繁忙的Z市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。在详细考察了N名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。那么,应如何分配罪犯,才能使Z市长看到的那个冲突事件的影响力最小?这个最小值是多少?
输入文件的每行中两个数之间用一个空格隔开。
第一行为两个正整数N和M,分别表示罪犯的数目以及存在仇恨的罪犯对数。
接下来的M行每行为三个正整数aj,bj,cj,表示aj号和bj号罪犯之间存在仇恨,其怨气值为cj。
数据保证1<=aj<=bj<=N,0<=cj<=1000000000,且每对罪犯组合只出现一次。
输出文件共1行,为Z市长看到的那个冲突事件的影响力。如果本年内监狱中未发生任何冲突事件,请输出0。
4 6
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884
3512
很好懂,就是把N个犯人分配到2所监狱里面去,但某一些犯人之间会出现怨气值,
如果,可以把有矛盾的所有犯人分开到两所监狱当然是最好的啦。ans=0
但是,如果不行,那么只能把影响降到最低(所指的最低不是所有犯人之间的怨气值的总和),
而是两所监狱中最大的怨气值的两位大佬的影响。ans=分配完的两所监狱后,最大影响力的两位大佬怨气值。
一开始我误解为把所有犯人之间的怨气值的总和最小了。。。。
我不会做,然后看了网上别人的做法才领悟了这道题的奥妙之处了。题目其实很明白就是给了两所监狱。
然后进行的操作是不断分配犯人。
尊重原创,以下代码参考这篇博客
#include
using namespace std;
typedef struct Edge{
int u,v,w;
}edge;
edge e[100500];
int pre[100500],tmp[100500];
int cmp(edge a,edge b){
return a.w>b.w;
}
int find_father(int x){
if(pre[x]==x) return x;
pre[x]=find_father(pre[x]);
return pre[x];
}
void Union(int x,int y){
int fx=find_father(x),fy=find_father(y);
if(fx!=fy){
pre[fx]=fy;
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
memset(pre,0,sizeof(pre));
memset(tmp,0,sizeof(tmp));
for(int i=1;i<=n;i++){
pre[i]=i;
tmp[i]=0;
}
sort(e+1,e+1+m,cmp);
for(int i=1;i<=m;i++){
int u=e[i].u;
int v=e[i].v;
int w=e[i].w;
int fu=find_father(u);
int fv=find_father(v);
if(fu==fv){
printf("%d\n",w);
return 0;
}
if(tmp[u]==0){
tmp[u]=v;
}else{
Union(v,tmp[u]);
}
if(tmp[v]==0){
tmp[v]=u;
}else{
Union(u,tmp[v]);
}
}
printf("0\n");
return 0;
}
不能再画图了,直接说就够明白了。
我们可以建图,2×M条边的无向图。通过DFS进行染色。
怎么得到答案呢,我们可以通过二分查询来找答案。
因为我们知道,如果我们固定一组关系时,只要二分过程中的Mid,比他小的边可以忽略。
只要我们能够建出二分图,R=mid
如果建不出二分图,L=mid+1;
最后找出答案
尊重原创,以下代码参考这个博客
#include
using namespace std;
const int N=20500;
const int M=100000;
typedef struct Edge{
int to,next,w;
}edge;
edge e[M<<1];
int head[N],cnt,n,m,W,a,b,c,ans,w[M],S[N];
void add_edge(int u,int v,int w){
e[cnt].to=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt++;
}
bool dfs(int u){
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
int w=e[i].w;
if(w<=W) continue;
if(S[u]==S[v])return false;
if(!S[v]){
S[v]=3-S[u];
if(!dfs(v))return false;
}
}
return true;
}
bool check(int x){
for(int i=1;i<=n;i++){
if(S[i]==0){
S[i]=1;
if(!dfs(i)) return false;
}
}
return true;
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
add_edge(a,b,c);
add_edge(b,a,c);
w[i]=c;
}
sort(w+1,w+m+1);
int L=1,R=m,mid;
while(L>1;
W=w[mid];
if(check(mid)){ ans=w[mid], R=mid; }
else L = mid+1;
}
if(L==1&&L>R){
printf("%d\n",0);
}else{
printf("%d\n",ans);
}
}