博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CodeforcesD. Aztec Catacombs
阅读量:5297 次
发布时间:2019-06-14

本文共 2311 字,大约阅读时间需要 7 分钟。

$n \leq 300000$的完全无向图,每条边有可行和不可行的状态,一开始只有$m \leq 300000$条边是可行的,给出。每次从$x$走到$y$时,所有与$x$相连的边的可行/不可行状态会改变。问从1最少走几步到$n$。

先考虑只走原来有的路,如果走原来有的路能到$n$,那么这可能是一种可行方案。如果要利用边状态的改变来到达$n$,最优地可以找一个距离为2的点,走到他,再回到1,然后一步到$n$,读者自证不难(考虑每一步如果会出现更优的利用原图没有的边来走会发生什么)。也就是说,直接走路程$\leq4$时直接走,否则找个距离2的绕一圈。

如果没有距离2的点,又不能到$t$,那么1所在的连通分量大概是个菊花,但菊花的叶子是有连边的。这时从1走出去再也回不到1,可删之,与1相连的点变成若干连通块。新到那个点叫$x$,如果$x$的连通块里有个距离$x$为2的点,那可以用上面的方法得到5的答案;如果没有,说明这个点与分量里的所有点有连边,那还要递归下去找吗?不必了,如果枚举所有与1相连的点做如此判断,得不到5的答案就无解了。证明可以联系大前提:没有与1距离大于1的点。

1 //#include
2 #include
3 #include
4 //#include
5 //#include
6 //#include
7 //#include
8 #include
9 #include
10 using namespace std;11 12 #define LL long long13 int qread()14 {15 char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);16 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;17 }18 19 //Pay attention to '-' , LL and double of qread!!!!20 21 int n,m;22 #define maxn 30001123 struct Edge{ int to,next;}edge[maxn<<1]; int first[maxn],le=2;24 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}25 void insert(int x,int y) { in(x,y); in(y,x);}26 27 int dis[maxn],pre[maxn],ufs[maxn],que[maxn],head,tail,du[maxn],size[maxn];28 int find(int x) { return x==ufs[x]?x:(ufs[x]=find(ufs[x]));}29 void Union(int x,int y) { if ((x=find(x))!=(y=find(y))) ufs[x]=y,size[y]+=size[x];}30 void bfs(int s)31 {32 for (int i=1;i<=n;i++) dis[i]=0x3f3f3f3f,pre[i]=0;33 head=tail=1; que[tail++]=s; dis[s]=0;34 while (head!=tail)35 {36 int x=que[head++];37 for (int i=first[x];i;i=edge[i].next)38 {39 Edge &e=edge[i]; if (e.to==1) continue;40 if (dis[e.to]==0x3f3f3f3f)41 {42 dis[e.to]=dis[x]+1;43 pre[e.to]=x;44 que[tail++]=e.to;45 }46 }47 }48 }49 50 int main()51 {52 n=qread(); m=qread();53 for (int i=1,x,y;i<=m;i++) {x=qread(); y=qread(); insert(x,y);}54 bfs(1);55 if (dis[n]<=4)56 {57 printf("%d\n1 ",dis[n]);58 int ans[10],lans=0;59 for (int i=n;i!=1;i=pre[i]) ans[++lans]=i;60 for (int i=lans;i;i--) printf("%d ",ans[i]);61 return 0;62 }63 for (int i=1;i<=n;i++) if (dis[i]==2)64 {65 printf("4\n1 %d %d 1 %d",pre[i],i,n);66 return 0;67 }68 for (int i=2;i
View Code

 

转载于:https://www.cnblogs.com/Blue233333/p/9191117.html

你可能感兴趣的文章
tensorflow的graph和session
查看>>
JavaScript动画打开半透明提示层
查看>>
Mybatis生成resulteMap时的注意事项
查看>>
jquery-jqzoom 插件 用例
查看>>
1007. Maximum Subsequence Sum (25)
查看>>
iframe的父子层跨域 用了百度的postMessage()方法
查看>>
图片生成缩略图
查看>>
动态规划 例子与复杂度
查看>>
查看oracle数据库的连接数以及用户
查看>>
【数据结构】栈结构操作示例
查看>>
中建项目环境迁移说明
查看>>
三.野指针和free
查看>>
activemq5.14+zookeeper3.4.9实现高可用
查看>>
TCP/IP详解学习笔记(3)IP协议ARP协议和RARP协议
查看>>
简单【用户输入验证】
查看>>
python tkinter GUI绘制,以及点击更新显示图片
查看>>
HDU4405--Aeroplane chess(概率dp)
查看>>
CS0103: The name ‘Scripts’ does not exist in the current context解决方法
查看>>
20130330java基础学习笔记-语句_for循环嵌套练习2
查看>>
Spring面试题
查看>>