好朋友

                                           好朋友

noip2011就要来了,W校的同学们不仅看重这次比赛,更看重noip2011和谁住在同一个房间。同学之间的关系好坏可以用一个亲密值表示,亲密值越大,两个同学关系越好。小A作为W校信息组的组长,自然想要让同学们在比赛前能好好休息,放松心情,让同学们在赛场上能够超常发挥。他现在知道自己预订的房间都是双人间,且知道这n个同学之间的关系。n个同学的关系可以用一个n条双向边的连通图来描述,即某个同学只愿意和与他有边相连的同学住同一个房间,边权即为两个同学的亲密值。数据保证没有重边、自环。现在小A想知道在让所有同学的要求满足的情况下,亲密值最低的一对同学亲密值最高是多少。

输入格式:

  第一行一个正整数n,下面n行每行三个数u,v,w,表示u到v有一条边权为w的双向边。

输出格式:

  假如无论如何都无法满足所有同学的要求,输出”no answer”,否则输出亲密值最低的一对同学的最高亲密值。

样例输入:

4
1 2 3
2 3 10
3 4 3
1 4 1

样例输出:

数据范围:

50%的数据满足n<=20;
80%的数据满足n<=1000;
100%的数据满足n<=100000,-10^9<=w<=10^9

时间限制:

1S

空间限制:

64M

提示:

remove!!!
本题目就是贪一波,因为该图的边数等于点数,所以该图一定是一个环每个点下挂棵树,然后我们把度为1的点不断匹配,不断删除,最后会剩下一个环或没东西,若是环就dfs跑出来,就两种取法,比一下即可。m>n/2直接puts(”no answer“);

复杂度(O(n))

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using  namespace  std;
#define N 400001
#define PER(i,a,b) for(int i=a;i<=b;i++)
bool  pg[N]; int  t[N]; int  val[N]; int  fi[N],cis; int  ond,sed; int  q[2*N]; int d[N],ne[N],cir[N],civ[N]; int  n,l,tot,ans=2e9,u,v,w,he,ta,onen;
void  s(){ puts ( "no answer" ); exit (0);}
void  add( int  u, int  v, int  w){t[++tot]=v;val[tot]=w;ne[tot]=fi[u];fi[u]=tot;}
void  init(){ scanf ( "%d" ,&n);PER(i,1,n) { scanf ( "%d%d%d" ,&u,&v,&w),add(u,v,w),add(v,u,w),d[u]++,d[v]++;} if (n%2) s();}
void  dfs( int  x, int  nownum)
{
     if (pg[x])  return ;
     cis=nownum;cir[nownum]=x;pg[x]=1;
     for ( int  i=fi[x];i;i=ne[i]){ if (!pg[t[i]]){dfs(t[i],nownum+1);civ[nownum]=val[i]; break ;}}
     return ;
}
int  main()
{
     init();he=ta=0;PER(i,1,n){ if (d[i]==1) q[++ta]=i; else  if (d[i]==0) s();}
     while (he++<ta)
     {
         if (pg[q[he]]) continue ;
         l=0;
         for ( int  i=fi[q[he]];i;i=ne[i])
         {
             if (!pg[t[i]]){l=t[i];pg[t[i]]=pg[q[he]]=1;ans=min(ans,val[i]); break ;}
         } if (!l)s();
         for ( int  i=fi[l];i;i=ne[i])
         {
             if (!pg[t[i]])
             {
                 if (--d[t[i]]==1) q[++ta]=t[i];
                 else  if (!d[t[i]]) s();
             }
         }
     }
     bool  flag=0;
     PER(i,1,n)  if (!pg[i]){ onen=i;flag=1; break ;}
     if (!flag) {cout<<ans; return  0;}
     dfs(onen,1);
     for ( int  i=fi[cir[cis]];i;i=ne[i])
     {
         if (t[i]==cir[1]) {civ[0]=val[i]; break ;}
     }
     sed=ond=ans;PER(i,1,cis/2){ond=min(ond,civ[i*2-1]);sed=min(sed,civ[i*2-2]);}
     ans=max(sed,ond);
     cout<<ans;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值