http://codeforces.com/contest/967/problem/F

题目大意:

有n个点,n*(n-1)/2条边的无向图,其中有m条路目前开启(即能走),剩下的都是关闭状态

定义:从x走到y(即x->y)后,和x所连接的边的所有状态都反转(即开启->关闭,关闭->开启)

问,从起点1走到终点n,最少需要经过几步,并且输出这个路径(如果存在多挑最短路径,输出任意一条)

如果不存在,则输出-1

思路:

其实这道题第一眼看过去就是bfs,不过,由于每个状态都在改变,那要怎么利用这个bfs的特性呢?

后来画了画图,你会发现,存在如下的问题。

对于一个a+1个点,b条边的图(其中终点,即a+1这个点是没有边连向它)来说,如果b=a*(a-1)/2,那么,无论如何都是走不到a+1这个点的。

所以,问题就转换成,如果b<a*(a-1)/2需要走几步。

于是我们可以发现,在b<a*(a-1)/2的情况中,我们又可以找出bb=aa*(aa-1)/2的情况。 其中bb表示b的子集,aa表示a的子集

于是不断剖析下去,最后只会得到两种情况

第一种:

a=3, b=2的情况(注,a=4才是终点,前面定义过了= =)

图形:①->②->③

即该情况步数是4步,即1->2->3->1->4

第二种:

a=4,  b=5的情况

(= =)一共4个点,告诉你边,你自己画吧

边为:

1 2

2 3

3 4

4 1

1 3

该情况步数是5

当然,可能存在步数<=4的情况,即从1出发直接按照题目所给边走到终点,这个就不用我说了吧!!!(具体为什么的话,请自己利用上面的两种情况分析一下)

所以根本不存在output中说的le6的情况

对于前面两种情况中,步数=4的情况是容易解决的,关键就是步数=5的情况容易TLE(= =,退役一年没做题,脑子锈逗了,T了一天)

首先我们可以发现步数=5的情况可以转移成——在删除起点1之后,步数=4的情况。

因此,我们只需要找一个从1->u的情况,设u包含u下面所有的子节点(不包含1)个数位C,那么如果该集合的节点个数(包含u)< u的边数,那么就存在解

解为1->u->v->z->u->n

然而= =,楼主先暴力u,再暴力v,再暴力z,T死我了

改成先暴力u,再暴力z,最后通过u、z找v就过了= =

原因是,因为你会发现,v满足的条件比z满足的条件要少,所以v的剪枝比较少,因此先暴力v所要判断的节点数目会更多,因此不优秀

(退役了以后做题是真的伤不起,还写得很麻烦= =,懒得优化了,自己看着办吧)

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = 5e5 + ;
int n, m;
vector<int> G[maxn];
bool vis[maxn];
int pre[maxn]; bool bfs(int u){
queue<pair<int, int> > que;
que.push(mk(, ));
memset(pre, -, sizeof(pre));
vis[] = ;
while (!que.empty()){
pair<int, int> p = que.front(); que.pop();
int u = p.fi, step = p.se;
//if (u == n) break;
for (int i = ; i < G[u].size(); i++){
int v = G[u][i];
if (vis[v]) continue;
vis[v] = true;
pre[v] = u;
if (step + <= ){
que.push(mk(v, step+));
}
}
}
while(!que.empty()) que.pop();
if (pre[n] == -) return false;
int pos = n;
vector<int> ans; ans.pb(pos);
while (pre[pos] != -){
ans.pb(pre[pos]);
pos = pre[pos];
}
reverse(ALL(ans));
if (ans.size() > ) return false;
printf("%d\n", ans.size()-);
for (int i = ; i < ans.size(); i++)
printf("%d ", ans[i]);
cout << endl;
return true;
} void display(int a, int b, int c, int d, int e, int f){
printf("5\n%d %d %d %d %d %d\n", a, b, c, d, e, f);
} void bfs2(int x, vector<int> &cache){
vis[x] = ;
queue<int> que;
que.push(x);
cache.pb(x);
while (!que.empty()){
int u = que.front(); que.pop();
for (int i = ; i < G[u].size(); i++){
if (vis[G[u][i]] || u == )continue;
vis[G[u][i]] = ;
que.push(G[u][i]);
cache.pb(G[u][i]);
}
}
} set<int> mys[maxn];
int main(){
cin >> n >> m;
for (int i = ;i <= m; i++){
int u, v; scanf("%d%d", &u, &v);
G[u].pb(v), G[v].pb(u);
mys[u].insert(v); mys[v].insert(u);
}
if (m == ) return puts("-1"), ;
if (n == ) return printf("1\n1\n"), ;
//direct from 1 to n
if (bfs()) return ;
memset(vis, , sizeof(vis));
//other(just 4 steps) for (int i = ; i < G[].size(); i++){//the next point which connect to 1
vis[G[][i]] = ;
}
for (int i = ; i < G[].size(); i++){
int u = G[][i];
for (int j = ; j < G[u].size(); j++){
int v = G[u][j];
if (v == || vis[v]) continue;
printf("4\n1 %d %d 1 %d\n", u, v, n);
return ;
}
}
//other(just 5 steps)
//1->u->v->z->u->n
memset(vis, , sizeof(vis));
vector<int> cache;
for (int i = ; i < G[].size(); i++){
int u = G[][i];
if (vis[u]) continue;
cache.clear();
bfs2(u, cache);
if (G[u].size() < cache.size()){
for (int j = ; j < cache.size(); j++){
u = cache[j];
if (!mys[u].count()) continue;
if (G[u].size() >= cache.size()) continue;
for (int k = ; k < G[].size(); k++){
int z = G[][k];
if (!vis[z] || mys[z].count(u) || z == u) continue;
if (G[z].size() >= cache.size()) continue;
for (int f = ; f < G[z].size(); f++){
int v = G[z][f];
if (!mys[v].count() || !mys[v].count(u)) continue;
if (v == ) continue;
display(, u, v, z, u, n);
return ;
}
} }
}
}
puts("-1");
return ;
} /*
5 5
1 2
2 3
3 4
4 1
1 3
*/

Codeforces Round #477 (rated, Div. 2, based on VK Cup 2018 Round 3) F 构造的更多相关文章

  1. Codeforces Round #477 (rated, Div. 2, based on VK Cup 2018 Round 3) E 贪心

    http://codeforces.com/contest/967/problem/E 题目大意: 给你一个数组a,a的长度为n 定义:b(i) = a(1)^a(2)^......^a(i), 问, ...

  2. Codeforces Round #477 (rated, Div. 2, based on VK Cup 2018 Round 3) D 贪心

    http://codeforces.com/contest/967/problem/D 题目大意: 有n个服务器,标号为1~n,每个服务器有C[i]个资源.现在,有两个任务需要同时进行,令他为x1,x ...

  3. 【枚举】【二分】Codeforces Round #477 (rated, Div. 2, based on VK Cup 2018 Round 3) D. Resource Distribution

    题意:有两个服务要求被满足,服务S1要求x1数量的资源,S2要求x2数量的资源.有n个服务器来提供资源,第i台能提供a[i]的资源.当你选择一定数量的服务器来为某个服务提供资源后,资源需求会等量地分担 ...

  4. Codeforces Round #470 (rated, Div. 2, based on VK Cup 2018 Round 1)A. Protect Sheep

    http://codeforces.com/contest/948/problem/A   A. Protect Sheep Bob is a farmer. He has a large pastu ...

  5. Codeforces Round #470 (rated, Div. 1, based on VK Cup 2018 Round 1) 923D 947D 948E D. Picking Strings

    题: OvO http://codeforces.com/contest/947/problem/D 923D 947D 948E 解: 记要改变的串为 P1 ,记目标串为 P2  由变化规则可得: ...

  6. Codeforces Round #470 (rated, Div. 2, based on VK Cup 2018 Round 1) C.Producing Snow

    题目链接  题意  每天有体积为Vi的一堆雪,所有存在的雪每天都会融化Ti体积,求出每天具体融化的雪的体积数. 分析 对于第i天的雪堆,不妨假设其从一开始就存在,那么它的初始体积就为V[i]+T[1. ...

  7. 【推导】【贪心】Codeforces Round #472 (rated, Div. 2, based on VK Cup 2018 Round 2) D. Riverside Curio

    题意:海平面每天高度会变化,一个人会在每天海平面的位置刻下一道痕迹(如果当前位置没有已经刻划过的痕迹),并且记录下当天比海平面高的痕迹有多少条,记为a[i].让你最小化每天比海平面低的痕迹条数之和. ...

  8. 【推导】Codeforces Round #472 (rated, Div. 2, based on VK Cup 2018 Round 2) B. Mystical Mosaic

    题意:给你一个棋盘的最终局面. 你的一次操作可以选择一些行和列,将它们的交叉点染黑,不能重复选择某行或者某列.问你是否能经过数次操作之后,达到目标局面. 就枚举所有黑点,如果该点行列都没被标记,就给它 ...

  9. Codeforces Round #470 (rated, Div. 2, based on VK Cup 2018 Round 1)

    A. Protect Sheep time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

随机推荐

  1. setBit testBit权限管理

    1.jdk7文档解释 public boolean testBit(int n) Returns true if and only if the designated bit is set. (Com ...

  2. css修改select下拉列表的默认样式

    select的一些默认样式我们很难修改,比如图标的替换.接下来就说说如何修改这些默认样式: html代码: <div> <select name=""> & ...

  3. Sqlserver_分组

    create table orders ( id int, orderName varchar() ) go create table cars ( id ,) , ordersid int, pna ...

  4. nginx 新增域名访问

    nginx 新增域名访问 1.申请阿里云域名 2.指向阿里云主机 3.配置nginx文件 server { listen 80; server_name zlx.test.com; set $root ...

  5. Intellij IDEA 2017 debug断点调试技巧与总结详解篇

    转载自csdn----------------------------------------------------------------------https://blog.csdn.net/q ...

  6. JavaScript高级程序设计学习笔记2

    垃圾收集原理: 找出不再使用的变量,然后释放其内存. js中最常用的垃圾收集方法是标记清除,当变量进入环境时,就将变量标记为“进入环境”,当变量离开环境时,将其标记为“离开环境”,最后由垃圾收集器完成 ...

  7. LeetCode 141. Linked List Cycle环形链表 (C++)

    题目: Given a linked list, determine if it has a cycle in it. To represent a cycle in the given linked ...

  8. Daily Scrumming* 2015.12.10 今天集体请假一天

    今天由于所有成员均在进行编译原理实验的相关工作,全体请假一天.......

  9. Linux第二周学习总结——操作系统是如何工作的

    第二周学习总结--操作系统是如何工作的 作者:刘浩晨 [原创作品转载请注明出处] <Linux内核分析>MOOC课程http://mooc.study.163.com/course/UST ...

  10. Day Two

    站立式会议 站立式会议内容总结 442 完成了计划列表和toolbar的事件监听部分 遇到问题:父组无法实现事件监听,只能实现点击折叠.展开的功能. 331 学习form中list数据添加 遇到的问题 ...