洛谷 Cx的故事

今天洛谷的比赛,由于CSDN好像是每天限制了5篇博客,4道题压一篇博客。—–2017年7月16日 15:33:10

Cx的治疗

题目背景
「Cx的故事」众所周知,Cx是一个宇宙大犇。由于Cx在空中花园失足摔下,导致他那蕴含着无穷智慧的大脑受到了严重的损伤,许多的脑神经断裂。于是,Cx的wife(有么?)决定请巴比伦最好的医师治疗。但是,Cx的wife是个十分吝啬的人,虽然她想将Cx治好,但是她又不肯出过多的钱,而脑神经的重新连接需要大量的花费。所以,当她知道来自未来的你时,她恳求你去帮她计算一下如何才能将Cx的神经元全部重新连接起来,而花费最小。
题目描述
神经网络就是一张无向图,图中的节点称为神经元,神经元已经按照1~N的顺序排好号,而且两个神经元之间至多有一条脑神经连接。
现有N个神经元,M条仍然完好的脑神经,连接神经元Ai与Bi。
医生给出能够连接的t条脑神经,分别连接神经元Aj与Bj,并给出连接所需的花费Ci。
请编写程序计算将所有神经元连通的最小花费w。
输入输出格式
输入格式:
第一行为两个整数N,M (1<=N<=10000,1<=M<=100000) 表示一共有N个神经元,有M条依旧完好的脑神经。
接下来M行每行有两个整数Ai,Bi (1<=Ai,Bi<=100000) 表示神经元Ai,Bi已经连在一起。
接下来一行有一个整数t (1<=t<=100000)表示医生能连接的神经个数。
接下来t 行有三个整数 Aj ,Bj ,Cj (1<=Ai,Bi,Cj<=100000) 表示神经元Aj,Bj能通过Cj的花费将其连在一起。
输出格式:
仅一行,为一个整数,表示将Cx的神经元连通起来的最小花费w。若不能将其全部连通,请输出-1。
输入输出样例
输入样例#1:
10 5
1 5
2 6
3 7
3 8
3 9
10
2 4 10
3 6 15
2 4 9
2 6 34
5 7 64
2 8 26
3 7 16
5 2 7
3 9 13
8 5 12
输出样例#1:
-1
输入样例#2:
10 5
1 5
2 6
3 7
3 8
3 9
10
8 10 10
3 6 15
2 4 9
2 6 34
5 7 64
2 8 26
3 7 16
5 2 7
3 9 13
8 5 12
输出样例#2:
38
说明
1<=N<=10000,0<=M<=100000;
1<=Ai,Bi,Aj,Bj<=10000;
1<=Cj<=100000;
1<=t<=100000;

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Edge{
    int u,v,w;
    bool operator < (const Edge & a) const {
        return w < a.w;
    }
}e[100005];
int t,n,m,fa[10005],tot,ans=0;
int Find(int x){
    if(x==fa[x]) return x;
    else return fa[x]=Find(fa[x]);
}
void Add_Edge(int u,int v,int w){e[++tot].u=u;e[tot].v=v;e[tot].w=w;}
int main(){
    scanf("%d%d",&n,&m);
    for(int u,v,w,i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        Add_Edge(u,v,0);
    }
    scanf("%d",&t);
    for(int i=1;i<=10000;i++) fa[i]=i;
    int cur=0;
    for(int u,v,w,i=1;i<=t;i++){
        scanf("%d%d%d",&u,&v,&w);
        Add_Edge(u,v,w);
    }
    sort(e+1,e+m+t+1);
    for(int i=1;i<=m+t;i++){
        int u=e[i].u,v=e[i].v;
        int rx=Find(u),ry=Find(v);
        if(rx==ry) continue;
        cur++; fa[rx]=ry;
        ans+=e[i].w;
        if(cur==n-1) break;
    }
    if(cur!=(n-1)) printf("-1");
    else printf("%d",ans);

    return 0;
}
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Edge{
    int u,v,w;
    bool operator < (const Edge & a) const {
        return w < a.w;
    }
}e[200005];//考试 80 分 只因 数组开小了 
int t,n,m,fa[10005],tot;
long long ans=0;
int Find(int x){
    if(x==fa[x]) return x;
    else return fa[x]=Find(fa[x]);
}
void Add_Edge(int u,int v,int w){e[++tot].u=u;e[tot].v=v;e[tot].w=w;}
int main(){
    scanf("%d%d",&n,&m);
    for(int u,v,w,i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        Add_Edge(u,v,0);
    }
    scanf("%d",&t);
    for(int i=1;i<=10000;i++) fa[i]=i;
    int cur=0;
    for(int u,v,w,i=1;i<=t;i++){
        scanf("%d%d%d",&u,&v,&w);
        Add_Edge(u,v,w);
    }
    sort(e+1,e+m+t+1);
    for(int i=1;i<=m+t;i++){
        int u=e[i].u,v=e[i].v;
        int rx=Find(u),ry=Find(v);
        if(rx==ry) continue;
        cur++; fa[rx]=ry;
        ans+=e[i].w;
        if(cur==n-1) break;
    }
    if(cur!=(n-1)) printf("-1");
    else printf("%lld",ans);

    return 0;
}

Cx大帝远征埃及

题目背景

众所周知,Cx是一个宇宙大犇。Cx能文善武,一直在为大一统的实现而努力奋斗着。Cx将调用他的精锐军队,一个精锐士兵最多可以战胜十个埃及士兵。同时Cx是个爱才的人,他想要制定一份能使在占领埃及的前提下,使自己的军队损失最小的作战方案。Cx可做好了充分的准备,他收集到了很多情报,经过了长期的准备,在今天这个伟大的日子,他终于作下了远征埃及的决定!

题目描述

Cx将会把他收集到的所有情报都汇总给你(当然不能有什么遗漏的),情报的内容包括了埃及的所有城市所驻扎的军队人数,和与其单向连通的城市(路程什么的对千里马来说不算什么)。编号1的城市即为首都,占领首都即战争胜利!他将会告诉你他调度的军队人数。

输入输出格式

输入格式:
第一行三个整数n和m,sum。n表示埃及的所有城市个数,m表示Cx大帝开始出征的城市标号,sum表示精锐军队的人数。

以下的n行,第i+1行即为关于埃及编号为i的城市的情报,第一个整数ai表示在此驻扎的军队人数,第二个整数pi表示与此城市连通的城市数目,接下来pi个整数为与其连通的城市编号。

输出格式:
第一行输出Cx大帝要想完成占领埃及的目标的最优攻占城市顺序方案。第二行输出精锐军队剩余的人数,详细格式见输出样例。如军队的人数过少无法使Cx大帝占领埃及,则输出”No way!”

输入输出样例

输入样例#1:
4 3 10
30 0
13 1 1
7 2 4 2
3 1 1
输出样例#1:
3->4->1
6
说明

样例说明:最少需要对付的埃及士兵为40个,而精锐士兵以一敌十,所以最后还有6个存活。 数据保证p1=0。

士兵杀8个死不了,下一次再解决两个就GG了。

对于100%的数据: 2<=n<=10000 pi<=100

#include<iostream>
#include<cstring>
#include<cstring>
#include<cstdio>
#include<queue>
#define INF 0x3f
using namespace std;
const int MAXN = 10005;
bool exist[MAXN];
int dis[MAXN],pre[MAXN],head[MAXN],tot,a[MAXN];
struct Edge{int to,value,next;}e[200005];
queue<int> q;
int SPFA(int s){
    memset(dis,INF,sizeof dis );
    memset(exist,0,sizeof exist );
    q.push(0); dis[0]=0; pre[0]=-1;
    while(!q.empty()){
        int u=q.front();q.pop();exist[u]=0;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].value){
                dis[v]=dis[u]+e[i].value; pre[v]=u;
                if(exist[v]==0){ q.push(v);exist[v]=1; }
            }
        }
    }
    if(dis[1]%10==0) return dis[1]/10;
    else return dis[1]/10+1;
}
void Add_Edge(int u,int v,int w){
    e[++tot].to=v;e[tot].value=w;
    e[tot].next=head[u];head[u]=tot;
}
int n,s,sum;
void DFS(int u){//化点权为边权
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        e[i].value=a[v];
        DFS(v);
    }
}
void Print(int u,int S){
    if(pre[u]!=0) Print(pre[u],S);

    if(u==S) printf("%d",u);
    else printf("->%d",u);
}
int main(){
    scanf("%d%d%d",&n,&s,&sum);
    for(int m,i=1;i<=n;i++){
        scanf("%d",&a[i]);
        scanf("%d",&m);
        for(int j=1,v;j<=m;j++){
            scanf("%d",&v);
            Add_Edge(i,v,0);
        }
    }
    Add_Edge(0,s,a[s]);
    DFS(0);
    int ans = sum-SPFA(0);
    Print(1,s);
    printf("\n%d\n",ans);
    return 0;
}
//上方代码为不知为何爆零代码
#include<iostream>
#include<cstring>
#include<cstring>
#include<cstdio>
#include<queue>
#define INF 0x3f
using namespace std;
const int MAXN = 50505;
bool exist[MAXN];
int n,s,sum;

int dis[MAXN],pre[MAXN],head[MAXN],tot,a[MAXN],print[MAXN];
struct Edge{int to,next;}e[4000005];
queue<int> q;
int SPFA(int s){
    for(int i=0;i<=n;i++) dis[i]=99999999,exist[i]=0;
    q.push(s); dis[s]=a[s]; pre[s]=0;
    while(!q.empty()){
        int u=q.front();q.pop();exist[u]=0;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(dis[v]>dis[u]+a[v]){
                dis[v]=dis[u]+a[v]; pre[v]=u;
                if(exist[v]==0){ q.push(v);exist[v]=1; }
            }
        }
    }
    return ;
}
void Add_Edge(int u,int v){
    e[++tot].to=v;e[tot].next=head[u];head[u]=tot;
}
void Print(int u,int S){
    tot=0;int now=1;
    while(now!=S){
        print[++tot]=now;now=pre[now];
    }
    print[++tot]=S;
    for(int i=tot;i>=2;i--)
        printf("%d->",print[i]);
    printf("%d\n",1);
}
int main(){
    memset(head,-1,sizeof head );
    scanf("%d%d%d",&n,&s,&sum);
    for(int m,i=1;i<=n;i++){
        scanf("%d",&a[i]);
        scanf("%d",&m);
        for(int j=1,v;j<=m;j++){
            scanf("%d",&v);
            Add_Edge(i,v);
        }
    }
    SPFA(s);
    if(dis[1]<=sum*10) {
        Print(1,s);
        printf("%d\n",sum-dis[1]/10);
    }
    else printf("No way!");
    return 0;
}

Cx的金字塔

题目背景

「Cx的故事」众所周知,Cx是一个宇宙大犇。Cx终于修好了他的脑回路最近利用他的脑神经占领了埃及,成为了埃及的新一代法(yan)老(hou),他打算为自己的脑神经修一座纪(jin)念(zi)碑(ta)。于是他开始召集他的奴隶们开始修建纪(jin)念(zi)碑(ta),但愤怒的奴隶们经常会“不小心”打坏石头,以表示反抗,有时甚至向富(qiong)甲(de)一(yao)方(si)的Cx要工资!!!这是决不能允许的。所以,他打算启用他爷爷赦普塞卡夫斯奈夫鲁(Shepseskaf 2472 - 2467)的小发明——木牛流骆驼来修建纪(jin)念(zi)碑(ta)。

题目描述

木牛流骆驼的形状是一个球(为什么是球?也许法老的骆驼都很肥吧)。在修建纪(jin)念(zi)碑(ta),木牛流骆驼被用于在方形场地中搬运石块。储藏室是一个N*M的网格,有些格子为根据《埃及王国劳动权益法》为了自身利益合法游行示威的奴隶,所以Cx不敢让木牛流骆驼干扰他们。木牛流骆驼的中心总是在格点上,当然,木牛流骆驼必须在最短的时间内把物品搬运到指定的地方。木牛流骆驼接受的指令有:先前移动一步,两步或三步;转向。每个指令所需要的时间为1秒。请你计算一下木牛流骆驼完成任务所需的最少时间。注意:木牛流骆驼由于过于巨大(肥胖),占一个2X2的方格!

输入输出格式

输入输出格式

输入格式:
输入的第一行为两个正整数N,M(N,M<=50),下面N行是方形场地的构造,0表示无奴隶,1表示有奴隶,数字之间用一个空格隔开。接着一行有四个整数和一个大写字母,分别为起始点和目标点左上角网格的行与列,起始时的面对方向(东E,南S,西W,北N),数与数,数与字母之间均用一个空格隔开。终点的面向方向是任意的。

输出格式:
一个整数,表示完成任务所需的最少时间。如果无法到达,输出-1。

输入输出样例

输入样例#1:
9 10
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 1 0
7 2 2 7 S
输出样例#1:
12
说明

说明 n,m<=50;注意时间空间限制比较坑->_<-

//曾经有个题叫 机器人搬重物
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 55
const char dirs[]="NESW";
//const int dr[]= {-1,0,1,0};
//const int dc[]= {0,1,0,-1}; 
int a[maxn][maxn],dis[maxn][maxn][4];//a是题目中的网格,dis是初始状态到状态(r,c,dir)的最短距离
int ans,n,m,fx,fy,bx,by,bdir;
struct Node{
    int r,c,dir;//dir=0/1/2/3分别对应NESW
    Node(int r=0,int c=0,int dir=0):r(r),c(c),dir(dir) {}
};
int dir_id(char c) {
    return strchr(dirs,c)-dirs;
}
Node Turn(const Node& u, int k) {
    int dir=u.dir;
    if(k==1){dir=(dir+3)%4;} // 左转
    if(k==2){dir=(dir+1)%4;} // 右转
    return Node(u.r,u.c,dir);
}
void BFS() {
    queue<Node> q;
    memset(dis,-1,sizeof(dis));
    Node u(bx,by,bdir);
    dis[u.r][u.c][u.dir]=0;
    q.push(u);
    while(!q.empty()) {
        Node u=q.front(); q.pop();
        if(u.r==fx&&u.c==fy) {
            cout<<dis[fx][fy][u.dir]<<endl;
            return;
        }
        for(int i=1; i<=2; i++) { //转弯的两种情况,1表示逆时针,2表示顺时针
            Node v=Turn(u,i);
            if(v.r>=1&&v.r<n&&v.c>=1&&v.c<m&&dis[v.r][v.c][v.dir]==-1) {
                dis[v.r][v.c][v.dir]=dis[u.r][u.c][u.dir]+1;
                q.push(v);
            }
        }
        for(int i=1; i<=3; i++) { //前行的三种情况
            Node v(u.r+u.dir*i,u.c+u.dir*i,u.dir);
            if(v.r>=1&&v.r<n&&v.c>=1&&v.c<m&&dis[v.r][v.c][v.dir]==-1) {
                if(a[v.r][v.c]) break;
                dis[v.r][v.c][v.dir]=dis[u.r][u.c][u.dir]+1;
                q.push(v);
            }
        }
    }
    cout<<-1<<endl;
}
int main() {
    memset(a,0,sizeof(a));
    cin>>n>>m;
    for(int i=1; i<=n; i++){ //注意,由于这里的目的是读取障碍,所以横纵坐标从1开始编号,而实际上程序中的网格横纵坐标均为从0开始编号
        for(int temp,j=1; j<=m; j++){
            cin>>temp;
            if(temp) {
                a[i-1][j-1]=a[i][j-1]=a[i-1][j]=a[i][j]=1;//一个网格上的障碍,可以等价于其四个顶点都不能到达
            }
        }
    }
    char temp;
    cin>>bx>>by>>fx>>fy>>temp;
    bdir=dir_id(temp);
    BFS();
    return 0;
}

Cx的空中花园

题目背景
「Cx的故事」众所周知,Cx是一个宇宙大犇.Cx在占领了埃及之后,他为了完成大一统的梦想,他成功地征服了巴比伦。这天Cx在空中花园中漫步,这个神秘的花园里面有好多好多的花啊,还有很多绝迹的植物!这些宝贵的花分为3种:白蛇根草(white),曼陀罗(luo),尸香魔芋(unreality).
现有一个花坛(A坛)装满了白蛇根草,还有两个空花坛(B坛,C坛),尤其B,C坛的可以放的总花数恰好等于A坛的放花数。这三个花坛都被下了古老的诅咒,任何花在A坛里都会变为白蛇根草,在B坛里都会变为曼陀罗,在C坛里都会变为尸香魔芋。但是Cx觉得太单调了,又要做到低调奢华有内涵。所以现在Cx希望能拥有两种不同的花,且为了满足他的强迫症,两种花的数量必须相同。
为此,Cx请来了一名花匠。这个花匠很聪明,为了赚更多的钱,他告诉Cx:因为花坛的诅咒,他一次只能把一个花坛里的花移栽到另一个花坛中,每次要么就把前者中的花全部移到后者中去,要么就用前者中的花填满后者,每次移栽的花费为w。Cx一听就识破了花匠的“诡计”,但他觉得这个规则听起来很有趣,决定玩一玩。
题目描述
经过Cx的目测,他知道了A,B,C坛的能放的最大花数。Cx花了一毫秒就想到了他最少需要支付的工资,同时他也想到了最后他将拥有哪两种花。Cx想和你分享这个游戏的乐趣!
输入输出格式
输入格式:
共一行,第一行四个正整数a,b,c,w。a,b,c分别表示A,B,C坛的能放的最大花数,w表示花匠每移栽一次,Cx要付的工资。
输出格式:
共两行。
第一行为一个正整数,表示Cx需要付的最少工资。
第二行有两个单词(white,luo,unreality三选二),按照字典序输出,中间一个空格隔开。
输入输出样例
输入样例#1:
8 5 3 2
输出样例#1:
14
luo white
说明
输入数据保证有解且有唯一解。
对于70%的数据:
2<=a<=250
对于100%的数据:
2<=a<=2^60
b,c

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值