2014新生暑假个人排位赛06

时间限制 3000 ms  内存限制 65536 KB

题目描述

小弱的学校很喜欢修路,现在给你一张他学校的地图,地图上有n个点和m条双向边,每条边代表一条路,这条路有可能是畅通,也有可能正在修路。大家都知道修路使得交通很不方便。所有小弱很想学校快快的把路修好,使得他能够很轻松的到达主楼915去刷题。但考虑到学校的施工能力有限,小弱想让你帮他算出学校需要集中力量马上修好的最少路数,使得他能够从学校任意点出发,在不经过正在施工的路下到达主楼(编号为1)。

输入格式

有多组数据。
每组数据以n( 1<=n<=10000), m(1<=m<=200000)开头。接下来一行有m行数。每行有三个数,对应于u, v, s,分别为这条路的两端点(编号从1到n)和路况,s = 0代表畅通, s = 1 代表正在修路。输入保证图是连通图。

 

输出格式

对每组数据输出对应的最少路数。

输入样例

3 2
1 2 0
1 3 1
3 2
1 2 0
1 3 0
3 2
1 2 1
1 3 1

输出样例

1
0
2
比赛的时候莫名其妙用最短路wa了N次,最后居然被AK了。。太尴尬。得早睡了。。。


#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int father[10010],rank[10010],vis[10010];

int find(int x){
    if(x==father[x])return x;
    else return father[x]=find(father[x]);
}

void unite(int x,int y){
    x=find(x);
    y=find(y);
    father[x]=y;
}

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        for(int i=0;i<=n;i++)
            father[i]=i;
        for(int i=0;i<m;i++){
            int u,v,s;
            scanf("%d%d%d",&u,&v,&s);
            if(s==0) unite(u,v);
        }
        int ans=0;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
            vis[find(i)]=1;
        for(int i=1;i<=n;i++)
            if(vis[i])
                ans++;
        printf("%d\n",ans-1);
    }
    return 0;
}


时间限制 4000 ms  内存限制 65536 KB

题目描述

小弱有n个玩具,现在小弱想把他们排列成一行,把玩具j放在玩具i的右边相邻的位置上,他将得到一个高兴值Hij.

输入格式

输入有多组数据。
每组数据以一个整数n(n <= 18)开头。
接下来n行, 每行n个整数。 第i行第j列Hij( Hij的绝对值 <= 10000)代表把玩具j放在玩具i的右边相邻的位置时高兴值。输入保证Hii = 0,最左边只考虑与右边相邻的玩具,最右边只考虑与左边相邻的玩具。

 

输出格式

对于每组数据输出最大高兴值。

输入样例

2
0 1
2 0
3
0 -1 7
3 0 3
3 3 0

输出样例

2 
10

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 200000
using namespace std;

int n;
int d[19][19];
int dp[1<<19][19];
int vis[1<<19][19];

int rec(int S,int v){
    if(vis[S][v]==1)
        return dp[S][v];
    if(S==(1<<n)-1)
        return dp[S][v]=0;
    int res=-INF;
    for(int u=0;u<n;u++)
        if(!(S>>u&1))
            res=max(res,rec(S|1<<u,u)+d[v][u]);
    vis[S][v]=1;
    return dp[S][v]=res;
}

int main()
{
    while(~scanf("%d",&n)){
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&d[i][j]);
        int ans=-INF;
        for(int i=0;i<n;i++)
            ans=max(ans,rec(1<<i,i));
        printf("%d\n",ans);
    }
    return 0;
}

问了zsp,借鉴了她的代码,旅行商问题,晓得了。


时间限制 1000 ms  内存限制 65536 KB

题目描述

给你n个数,请你将他们从小到大输出出来。

输入格式

多组数据。

输入第一行为n,接下来一行给出n个数,每个数在0到10000。

输入文件大小为8.2MB。

输出格式

输出一行,排序之后的n个数。

输入样例

3
4 2 1

输出样例

1 2 4
好坑,要分析数据,考虑一下n的范围,用不同排序。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>

using namespace std;

int a[10001];
int vis[10001];

int main()
{
    int n;
    while(~scanf("%d",&n)){
        memset(vis,0,sizeof(vis));
        if(n<2000){
            int num=0;
            for(int i=0;i<n;i++){
                int x;
                scanf("%d",&x);
                if(vis[x]==0) a[num++]=x;
                vis[x]++;
            }
            sort(a,a+num);
            for(int i=0;i<num;i++)
                while(vis[a[i]]!=0){
                    vis[a[i]]--;
                    printf("%d ",a[i]);
                }
                printf("\n");
        }
        else {
            int MAX=-1,MIN=10001;
            for(int i=0;i<n;i++){
                int x;
                scanf("%d",&x);
                a[x]++;
                if(x>MAX) MAX=x;
                if(x<MIN) MIN=x;
            }
            for(int i=MIN;i<=MAX;i++)
                while(a[i]!=0){
                    a[i]--;
                    printf("%d ",i);
                }
            printf("\n");
        }
    }
    return 0;
}


时间限制 1000 ms  内存限制 65536 KB

题目描述

在星际时代,每个帝国都靠着贸易路线连接着各个联盟星球,这些贸易路线都是双向可达的。一个帝国的综合实力由他贸易连接着的联盟星球数决定。
学姐作为Mays帝国的领袖,长期与Luke帝国保持着敌对关系,爱好和平的学姐希望结束长达几个世纪的战争,于是找实验室定做了一颗代号小苹果的炸弹,可以定点摧毁一颗星球,这颗星球被毁后,与它相连的全部贸易就都被切断了,这样Luke帝国可能就被切断为一个小联盟,他们就再也不会对学姐的地位构成威胁啦~
经过调查,Luke帝国为了节约经费,他的联盟星之间都有且仅有一条直接或间接的贸易通路。
现在给出Luke帝国的贸易线路,学姐想知道摧毁哪一颗行星可以使得分裂后的若干Luke联盟威胁最大的分部最小。

输入格式

输入有多组数据,组数不大于10组。每一组开头一行为n,m,表示Luke帝国的联盟星球数量,和贸易关系数,接下来m行,每行两个整数u,v,表示星球u,v之间存在直接的贸易路线,1<=u,v<=n,1<=n,m<=100000

输出格式

输出一个数表示推荐学姐摧毁的星球,如果有多解,输出编号最小的一个。

输入样例

5 4
1 2
1 3
1 4
4 5

输出样例

1
题目就是有一颗连通的树,去掉某一结点后,剩下的子树的节点最小。所以就dfs一遍,统计每一个节点子树的所有节点数,然后dp[i]=max(num[i],n-num[i]),再找最小的dp[i].



/*
USER_ID: test#wlwlxgg
PROBLEM: 444
SUBMISSION_TIME: 2014-07-27 23:50:17
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define INF 100010
using namespace std;
 
struct {int to,next;}e[200010];
int head[100010],cnt;
int n,m;
int dp[100010],num[100010];
 
void add(int u,int v){
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt;
    cnt++;
}
 
void init(){
    for(int i=0;i<=n;i++){
        head[i]=0;
        dp[i]=0;
        num[i]=0;
    }
    cnt=1;
}
 
int dfs(int u,int fa){
    num[u]=1;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa)continue;
        else  num[u]+=dfs(v,u);
    }
    dp[u]=n-num[u];
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa)continue;
        else dp[u]=max(num[v],dp[u]);
    }
    return num[u];
}
 
int main()
{
    while(~scanf("%d%d",&n,&m)){
        init();
        for(int i=0;i<m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1,0);
        int ans=INF;
        for(int i=1;i<=n;i++)
            ans=min(ans,dp[i]);
        for(int i=1;i<=n;i++)
            if(ans==dp[i])
                {printf("%d\n",i);break;}
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值