蒟蒻退役记————————————(3)
十二月七日 今天又是爆零的一天因为根本没交
伤心地我说不出话来
๐·°(৹˃﹏˂৹)°·๐
T1、
1、万能遥控器(ipv6.cpp)
【题目描述】
Z企业有各种各样的机器人。为了控制所有机器人,操作员Tom造了一个“万能遥控器”。只要向遥控器输入一个机器人的IP地址,就能遥控这个机器人。可是机器人实在太多,以至于使用IPv4协议都不能够唯一地标记每一个机器人。Tom听说Ipv6协议拥有近无穷个地址,于是他就想用IPv6协议为机器人设定IP地址。
不过,完整的IPv6地址很长(有39个字符),手工输入很费时间,所以IPv6有一套简化的机制。
IPv6的地址定义如下:
IPv6的地址有128位,以16位为一分组,每个16位分组写成4个十六进制数,中间用冒号分割,称为冒号分十六进制格式。
例如:21DA:00D3:0000:2F3B:02AA:00FF:FE28:9C5A 是一个完整IPv6地址。
IPv6地址中每个16位分组中的前导零位可以去除做简化表示,但每个分组必须至少保留一位数字。如上例中的地址,去除前导零位后可写成:
21DA:D3:0:2F3B:2AA:FF:FE28:9C5A
某些地址中可能包含很长的零序列,为进一步简化表示法,还可以将冒号十六进制格式中相邻分组的连续零位合并,用双冒号“::”表示。“::”符号在一个地址中只能出现一次,该符号也能用来压缩地址中前部和尾部相邻的连续零位。
注意:(一个单独的0分组不能使用“::”省略。
例如地址:
样例一:1080:0:0:0:8:800:200C:417A 可表示为压缩格式 1080::8:800:200C:417A
样例二:0:0:0:0:0:0:0:1 可表示为压缩格式 ::1
样例三:0:0:0:0:0:0:0:0 可表示为压缩格式 ::
现在,Tom给了你一些IPv6地址,请你编写程序,把它们转换成完整的地址。
给你N个字符串,判断其是否合法,并转为如0000:0000:0000:0000:0000:0000:0000:0000(八组)的形式
压缩方式:
1.省略每组的前置零(如果只有一个不省)
2.每个数字为十六进制
3.连续两个冒号表示省略一串0(只准出现一次)
【输入格式】
第一行为一个正整数N,表示将有N个IP地址。
接下来有n行,每行一个非空字符串,表示一个地址。输入只包含数字、大写字母、冒号(:)和换行符,输入每行不超过39个字符。
【输出格式】
输出一共N行,每行一个字符串。对每个输入的字符串,如果符合IPv6标准,则输出其对应的完整的IPv6地址,否则输出“INVALID”
【输入样例】
4
1080::8:800:200C:417A
::1
::
1234567890ABCDEF
【输出样例】
1080:0000:0000:0000:0008:0800:200C:417A
0000:0000:0000:0000:0000:0000:0000:0001
0000:0000:0000:0000:0000:0000:0000:0000
INVALID
【数据范围】
对100%的数据,保证:1≤N≤35
分析:模拟就完了但是这鬼东西太讨厌了
#include<bits/stdc++.h>
using namespace std; char s[100],a[100];
int n; int main()
{ //freopen("ipv6.in","r",stdin); //freopen("ipv6.out","w",stdout); scanf("%d\n",&n); for(int ii=1;ii<=n;ii++) { memset(s,'0',sizeof(s)); memset(a,'0',sizeof(a)); char c; int p1=0,p2=0,p3=0,p4=0,k=0,point=0; while((c=getchar())!=EOF && c!='\n') { s[++k]=c; if(c==':') {p1=0; p2++;} else p1++; if(p1>4 || p2>7) p4=1; if(c==':' && s[k-1]==':') {p3++;point=k;} if(p3>1) p4=1; } if(!p3 && p2<7) p4=1; if(p3 && p2==7 && point!=2 && point!=k) p4=1; for(int i=1;i<=k;i++) a[i]=s[k-i+1]; if(p4) {printf("INVALID\n");continue;} int q=0; p1=0; for(int i=1;i<=k;i++) { s[++q]=a[i]; p1++; if(a[i]==':') { q--; while(p1<5) { s[++q]='0'; p1++; } s[++q]=':'; p1=0; if(a[i+1]==':') { while(p2<=7) { for(int j=1;j<=4;j++) s[++q]='0'; s[++q]=':'; p2++; } q--; p1=4; } } } for(int i=39;i>=1;i--) printf("%c",s[i]); cout<<endl; } return 0; }
T2\
3、星球大战(starwar.cpp)
【问题描述】
很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系。某
一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有
的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。但好景不长,很快帝国又重
新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。
由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。
现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝
国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通快的个
数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连
通块中)。
给你一个无向联通图,每次操作删去一个点,求连通块总数
【输入格式】
输入文件第一行包含两个整数,N(1≤N≤2M)和 M(1≤M≤200,000),分别表示星
球的数目和以太隧道的数目。星球用 0~N-1的整数编号。
接下来的 M 行,每行包括两个整数 X,Y,其中 X,Y∈[0,N) 且 X≠Y ,表示星球 X
和星球 Y 之间有以太隧道。注意所有的以太隧道都是双向的。
之后输入一个整数 K(K≤N),表示帝国计划打击的星球个数。
接下来 K 行,每行一个星球编号 Di(0≤Di<N),表示打击的星球编号顺序。
【输出格式】
输出文件的第一行是开始时星球的连通块个数。接下来的K行,每行一个整数,表示经
过该次打击后现存星球的连通块个数。
【输入样例】starwar.in
8 13
0 1
1 6
6 5
5 0
0 6
1 2
2 3
3 4
4 5
7 1
7 2
7 6
3 6
5
1
6
3
5
7
【输出样例】starwar.out
1
1
1
2
3
3
【数据范围】
对于20%的数据,M≤10;
对于另20%的数据,N≤10000;
对于100%的数据,M ≤200000
这道题我们可以反过来做,怎么说呢,你可以先从最后最少的点开始(因为我们并不会删点),往前做,再倒着输出,就行了
#include <bits/stdc++.h>
using namespace std; const int X = 400005;
int father[X],a[X],ansout[X],first[X],tol,tot,n,m;
bool use[X]; struct node{ int x,y,next;
}edge[X*2]; void add(int x,int y) //建立邻接表(x、y连成的边正反建了2次)
{ edge[++tol].x = x; edge[tol].y = y; edge[tol].next = first[x]; first[x] = tol;
} int find_set(int x) //并查集找祖先
{ if(x!=father[x]) father[x] = find_set(father[x]); return father[x];
} void init()
{ memset(first,0,sizeof(first)); tol = 0; for(int i=1;i<=n;i++) { use[i] = true; father[i] = i; //并查集初始化,每个星球都是一个独立集合 } int x,y; for(int i=1;i<=m;i++) //读入m条边并建立邻接表 { scanf("%d%d",&x,&y); x++; y++; //星球的编号从1开始 add(x,y); //建边,邻接表 add(y,x); //反向建边 } cin >> tot; for(int i=1;i<=tot;i++) { scanf("%d",&a[i]); //读入要摧毁的星球 a[i]++; //星球的编号从1开始 use[a[i]]=false; //要摧毁的标记 }
} void solve() //统计摧毁K个星球后的联通快个数
{ int x,y,px,py; //点x、y连成的边正反建了2次,并且编号相邻 for(int i=1;i<=tol;i+=2) //枚举所有边,通过并查集,合并边的两个端点,形成一个联通块 { x = edge[i].x; y = edge[i].y; if(use[x]&&use[y]) //都不是要摧毁的点,建立并查集 { px = find_set(x); py = find_set(y); father[px] = py; } } int ans = 0; for(int i=1;i<=n;i++) //统计全部摧毁后的连通块的数量 if(use[i]&&father[i]==i) ans++; for(int i=tot;i;i--) //倒着枚举加入摧毁的点 x=a[i] { ansout[i] = ans; int x = a[i]; use[x] = 1; ans ++; //增加一个点,则假设增加一个联通快 for(int j=first[x];j;j=edge[j].next) //枚举从x出发的每一条边 { int y = edge[j].y; //y为x出发的边对面端点 if(use[y]) { py = find_set(y); px = find_set(x); if(px!=py) //祖先不一致,则合并 { father[px] = py; ans --; //连通块减一 } } } } ansout[0] = ans; //没有摧毁任何一个星球的答案 for(int i=0;i<=tot;i++) cout<<ansout[i]<<endl; //输出依次催毁的相应星球
} int main()
{ freopen("starwar.in","r",stdin); freopen("starwar.out","w",stdout);cin >> n >> m; init(); solve(); return 0;
}
T3\
- 次小生成树(tree.cpp/c/pas)
【问题描述】
小 C 最近学了很多最小生成树的算法,Prim 算法、Kurskal 算法、消圈算法等等。 正
当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了。小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的。
这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。
【输入格式】
第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y
z 表示,点 x 和点y之间有一条边,边的权值为z。
【输出格式】
包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生
成树)
【输入样例】tree.in
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
【输出样例】tree.out
11
【数据范围】
数据中无向图无自环;
50% 的数据N≤2000 M≤3000;
80% 的数据N≤50000 M≤100000;
100% 的数据N≤100000;M≤300000,
边权值非负且不超过 10
以前我们曾经学过求最小生成树,可以再此基础上进行次小生成树的探究,通过思考我们不难发现:假如说我们找到了最小生成树,删除它的某一条边,再连上另一条边,对每条边进行,若这两边差值最小,则树的总权值即为次小生成树的总权值
#include<bits/stdc++.h>
using namespace std; #define LL long long const LL INF=(LL)1e12;
const int N=(int)1e5 + 20;
const int M=3*(int)1e5 + 20;
int n,m,size,father[N],first[N];
int d[N],g[N][20],maxx[N][20][2];
int mx[2],p[N*3];
bool b[M],v[M];
LL ans,mst; struct node
{ int a; int b; int c;
}e[M]; struct node1
{ int to; int len; int next;
}bian[M*2]; void inser(int x,int y,int w)
{ size++; bian[size].next=first[x]; first[x]=size; bian[size].to=y; bian[size].len=w;
} void init()
{ scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
} bool cmp(const node &a,const node &b)
{ return a.c<b.c;
} int search(int v)
{ if (father[v]==v) return v; father[v]=search(father[v]); return father[v];
}
void MST() //krusakal算法求最小生成树
{ for (int i=1;i<=n;i++) father[i]=i; int t=0; sort(e+1,e+m+1,cmp); //按边的长度排序 for (int i=1;i<=m;i++) //从小到大枚举每条边 { int x=search(e[i].a); int y=search(e[i].b); if (x!=y) //第i条边两端不在一个集合 { father[x]=y; //合并 mst+=e[i].c; //最小生成树的权值 t++; b[i]=true; //标记i边已经放进最小生成树 inser(e[i].a,e[i].b,e[i].c); //把i边建立邻接表 inser(e[i].b,e[i].a,e[i].c); //反向建立邻接表 } if (t==n-1) break; //如果加进了n-1条边,则最小生成树加边完成 }
} void up_max(int &a,int &b,int w) //更新
{ if (w>a) {b=a;a=w;return;} if (w>b&&w!=a) {b=w;return;}
}
void bfs()
{ memset(g,-1,sizeof(g)); int head=0,tail=1; d[1]=1; p[1]=1; //d是深度;点1入队列 v[1]=true; while (head<tail) { int x=p[++head]; for (int u=first[x];u;u=bian[u].next) //枚举x出发的每条边 if (!v[bian[u].to]) //边指向的点不在队列中 { int y=bian[u].to; d[y]=d[x]+1; v[y]=true; g[y][0]=x; maxx[y][0][1]=bian[u].len; int k=0; while (g[y][k]!=-1) //倍增 maxx[y][k] 表示这段路径上的最长边和次长边 { g[y][k+1]=g[g[y][k]][k]; up_max(maxx[y][k+1][1],maxx[y][k+1][0],maxx[y][k][0]); up_max(maxx[y][k+1][1],maxx[y][k+1][0],maxx[y][k][1]); up_max(maxx[y][k+1][1],maxx[y][k+1][0],maxx[g[y][k]][k][1]); up_max(maxx[y][k+1][1],maxx[y][k+1][0],maxx[g[y][k]][k][0]); k++; } p[++tail]=y; } }
} int jump(int x,int l)
{ for(int i=19;i>=0;i--) if ((1<<i)<=l) { l-=1<<i; up_max(mx[1],mx[0],maxx[x][i][0]); up_max(mx[1],mx[0],maxx[x][i][1]); x=g[x][i]; } return x;
}
//最小生成树和次小生成树之间只有一边之差,枚举去掉哪条边,新连接一条边会构成一个环,环上找最值
void find(int v)
{ int x=e[v].a,y=e[v].b,w=e[v].c; mx[0]=mx[1]=0; if (d[x]<d[y]) swap(x,y); x=jump(x,d[x]-d[y]); if (x==y) { if (w!=mx[1])ans=min(ans,mst+w-mx[1]); else ans=min(ans,mst+w-mx[0]); } for (int i=19;i>=0;i--) if (g[x][i]!=g[y][i]) { up_max(mx[1],mx[0],maxx[x][i][0]); up_max(mx[1],mx[0],maxx[x][i][1]); up_max(mx[1],mx[0],maxx[y][i][0]); up_max(mx[1],mx[0],maxx[y][i][1]); x=g[x][i]; y=g[y][i]; } up_max(mx[1],mx[0],maxx[x][0][1]); up_max(mx[1],mx[0],maxx[y][0][1]); if (w!=mx[1])ans=min(ans,mst+w-mx[1]); else ans=min(ans,mst+w-mx[0]);
} int main()
{ ans=INF; init(); MST(); bfs(); for (int i=1;i<=m;i++) if (!b[i]) find(i); cout<<ans<<endl; return 0;
}
蒟蒻退役记————————————(3)相关推荐
- 蒟蒻のpython(记一个爬虫教程小网站)
虽然到处都有教程.. 但是为了水一篇博客 方便以后的查找,还是记一下,有需要的可以看看. 蒟蒻找的爬虫小网站 感觉开三门语言的专栏显得萌新都专业了不少呢!
- 二本蒟蒻的带牌退役感言(感谢两年来的acm经历)
TP 20年10月 20年 - 21年 寒假 22年开始,大二下 暑假后,怎么就大三了,时间好快 第47届icpc杭州站 尾声 润~ 20年10月 一个高考发挥失常的蒟蒻来到了化大.他带着不甘和兴奋走 ...
- 蒟蒻的HNOI2017滚粗记
蒟蒻的第一次省选,然而并没有RP爆发... Day 1: 8:00开考,(然而密码错误是什么鬼).跌跌撞撞,8:40终于拿到纸质试题. { T1:作为一名没有学过Splay的蒟蒻,考场上真的被出题人感 ...
- 记一枚蒟蒻的数模国赛参赛经历
ycy说:这次比赛我们体验的是人生,我认为没错. --题记 题目发布 9月13日晚8:00,从国赛群里get到了题目.这次的比赛题型一如往常:A题是"高温作业专用服装设计",草草看 ...
- NOIP2018退役记
NOIP2018退役记 手动博客搬家: 本文发表于20181112 08:25:07, 原地址https://blog.csdn.net/suncongbo/article/details/83961 ...
- NOIP2018 退役记
手动博客搬家: 本文发表于20181112 08:25:07, 原地址https://blog.csdn.net/suncongbo/article/details/83961273 以下为退役记 1 ...
- Noip2018 退役记(Last update 11/20)
窗外是黑白的世界 不变的时光令人烦闷 生存一事稍显沈重 若是纵身跃下 是否便会变得轻松 心中天气的预报 明天会是晴天吗? 投映眼中的每日景色 反正,还是,一样的吧 遗失在无尽延伸的道路的 某处了吗 我 ...
- 【原创】【个人向】CSP-S 2019 爆炸退役记 (已完成)
占坑. 说在前面 Day -84 蒟蒻就该有蒟蒻的亚子. 我有什么本事 我有什么进路 我自己清楚得很 Noip2016只参加了普及组. Noip2017Day2发高烧没去. Noip2018没有好好准 ...
- CCF NOI WC 2019 游记 by.一个云南蒟蒻
序 我是一个来自云南的蒟蒻. 大约是2018年八月份,我开始正式学习OI.在此之前,我约莫一直听说这世上有这么一种神奇的东西,兴许也曾路过,却从未走进这扇门来(大概是百度过,兴许是被铺天盖地的广告劝退 ...
- NOI2018 退役记
流水账警告:下方是流水账 上一次差点退役的时候是在省选的时候因为TJOI day1 t1一道线段树分治的入门题目 写了crt差点出队 今天的noi2018的day2t1 第一题是可以CRT来做 然后我 ...
最新文章
- 强制类型转换(Java)
- Ubuntu16.04LTS安装集成开发工具IDE: CodeBlocks 和Eclipse-cdt
- SD-WAN加速推动企业分支上云—Vecloud
- K2新网站(官网和BPM社区)正式上线了
- 构建之法第四章--两人合作
- Qt 字符串QString arg()用法总结
- 混合知识实例-本地GIS定位系统Web版(Java、vue、Geoserver)
- 官宣!CSDN 发布 C 站软件工程师能力认证
- 【Proteus仿真8086】将IO接口电路封装成子电路CCT001
- 《生产实习》实习报告——JAVA大数据工程师
- css固定定位的代码,CSS——相对定位、绝对定位、固定定位(示例代码)
- 美国旅游签证办理流程
- 开心消消乐简单消除检测
- 《富爸爸,穷爸爸》读后感——怎么实现财务自由
- 京东C2M的“马桶故事”
- 剑指offer 27. 二叉树的镜像
- 【CEGUI】概念简介
- securecrt linux ftp,如何通过SecureCRT FTP上传下载文件
- HTC One V卡刷RUU准备工作 图文教程详解
- Ackerman的非递归算法思路讲解
热门文章
- android和手环教程,智能手环怎么连接手机_智能手环连接手机教程
- 深信服python开发工程师面试经验,深信服软件工程师面试经验
- 汉字一、二级字库的汉字与unicode编码(十六进制)对照表,按照unicode的顺序排列
- 一个IT技术人员的回忆“痛并快乐着”
- 抖音新带货王诞生了:老把头和老解
- 合并石头的最低成本问题
- 地图学相关知识(二)
- zhuan [讲解] OI 字符串 常用哈希方法(by sxy sxy)
- (一百二十三)Android O 了解wifi eap中的anonymous identity
- 自尊是人生的高尚境界