好朋友

                                           好朋友

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];intd[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、付费专栏及课程。

余额充值