Scary Path Finding Algorithm
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 130 Accepted Submission(s): 47
Special Judge
Problem Description
Fackyyj loves the challenge phase in TwosigmaCrap(TC). One day, he meet a task asking him to find shortest path from vertex 1 to vertex n, in a graph with at most n vertices and m edges. (1 ≤ n ≤ 100,0 ≤ m ≤ n(n-1))
Fackyyj solved this problem at first glance, after that he opened someone's submission, spotted the following code:
long long spfa_slf() {
int n,m;
cin >> n >> m;
vector<pair<int,int> > edges[111];
for(int i = 0;i < m;i++) {
int x,y,w;
cin >> x >> y >> w;
edges[x].push_back(make_pair(y,w));
}
deque<int> q;
vector<long long> dist(n+1, ~0ULL>>1);
vector<bool> inQueue(n+1, false);
dist[1] = 0; q.push_back(1); inQueue[1] = true;
int doge = 0;
while(!q.empty()) {
int x = q.front(); q.pop_front();
if(doge++ > C) {
puts("doge");
return 233;
}
for(vector<pair<int,int> >::iterator it = edges[x].begin();
it != edges[x].end();++it) {
int y = it->first;
int w = it->second;
if(dist[y] > dist[x] + w) {
dist[y] = dist[x] + w;
if(!inQueue[y]) {
inQueue[y] = true;
if(!q.empty() && dist[y] > dist[q.front()])
q.push_back(y);
else
q.push_front(y);
}
}
}
inQueue[x] = false;
}
return dist[n];
}
Fackyyj's face lit up with an evil smile. He immediately clicked button "Challenge!", but due to a hard disk failure, all of his test case generators were lost! Fackyyj had no interest on recreating his precise generators, so he asked you to write one. The generator should be able to generate a test case with at most 100 vertices, and it must be able to fail the above code, i.e. let the above code print "doge". It should NOT contain any negative-cost loop.
For those guys who doesn't know C++, Fackyyj explain the general idea of the above algorithm by the following psuedo-code:
Fackyyj solved this problem at first glance, after that he opened someone's submission, spotted the following code:
long long spfa_slf() {
int n,m;
cin >> n >> m;
vector<pair<int,int> > edges[111];
for(int i = 0;i < m;i++) {
int x,y,w;
cin >> x >> y >> w;
edges[x].push_back(make_pair(y,w));
}
deque<int> q;
vector<long long> dist(n+1, ~0ULL>>1);
vector<bool> inQueue(n+1, false);
dist[1] = 0; q.push_back(1); inQueue[1] = true;
int doge = 0;
while(!q.empty()) {
int x = q.front(); q.pop_front();
if(doge++ > C) {
puts("doge");
return 233;
}
for(vector<pair<int,int> >::iterator it = edges[x].begin();
it != edges[x].end();++it) {
int y = it->first;
int w = it->second;
if(dist[y] > dist[x] + w) {
dist[y] = dist[x] + w;
if(!inQueue[y]) {
inQueue[y] = true;
if(!q.empty() && dist[y] > dist[q.front()])
q.push_back(y);
else
q.push_front(y);
}
}
}
inQueue[x] = false;
}
return dist[n];
}
Fackyyj's face lit up with an evil smile. He immediately clicked button "Challenge!", but due to a hard disk failure, all of his test case generators were lost! Fackyyj had no interest on recreating his precise generators, so he asked you to write one. The generator should be able to generate a test case with at most 100 vertices, and it must be able to fail the above code, i.e. let the above code print "doge". It should NOT contain any negative-cost loop.
For those guys who doesn't know C++, Fackyyj explain the general idea of the above algorithm by the following psuedo-code:
Input
Input contains several test cases, please process till EOF.
For each test case, there will be a single line containing an integer C. It is the constant C in the above code. (C <= 23333333)
For each test case, there will be a single line containing an integer C. It is the constant C in the above code. (C <= 23333333)
Output
For each test case, on the first line, print two integers, n and m, indicating the number of vertices and the number of edges of your graph. Next m lines, on each line print
x y w, means there is a road from x to y, cost w.
1 ≤ n ≤ 100,0 ≤ m ≤ n(n-1),|w| < 2 31. Note that your output shouldn't contain any negative-cost loop.
1 ≤ n ≤ 100,0 ≤ m ≤ n(n-1),|w| < 2 31. Note that your output shouldn't contain any negative-cost loop.
Sample Input
1
Sample Output
4 3 1 2 1 2 3 1 3 4 1
Author
Fudan University
Source
找个规律,使他的代码循环次数大于C。
官方题解:
图上第一个三角形,-8的位置对应了-2^n,-4的地方对应了-2^(n-1),后面按照类似的规则延伸下去即可,这样构造需要2n+1个点,可以使题中给出的算法的运行次数达到2^n。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <functional>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctime>
typedef long long ll;
//#pragma comment(linker, "/STACK:1024000000,1024000000") //手动扩栈
#define INF 1000000000LL
#define maxn 500
#define maxm 100086+10
#define mod 1000000007
#define eps 1e-7
#define PI acos(-1.0)
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define scan(n) scanf("%d",&n)
#define scanll(n) scanf("%I64d",&n)
#define scan2(n,m) scanf("%d%d",&n,&m)
#define scans(s) scanf("%s",s);
#define ini(a) memset(a,0,sizeof(a))
#define out(n) printf("%d\n",n)
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
cout<<61<<' '<<90<<endl;
int j = 30;
for(int i=1;j>=1;i+=2,j--)
{
printf("%d %d %d\n",i,i+1,0);
printf("%d %d %d\n",i+1,i+2,-(1<<j));
printf("%d %d %d\n",i,i+2,-(1<<j-1));
}
return 0;
}