hdu 4889 Scary Path Finding Algorithm

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:

 

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)
 

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.
 

Sample Input
  
  
1
 

Sample Output
  
  
4 3 1 2 1 2 3 1 3 4 1
 

Author
Fudan University
 

Source
 


找个规律,使他的代码循环次数大于C。

官方题解:

2014 <wbr>Multi-University <wbr>Training <wbr>Contest <wbr>3 <wbr>简要题解 <wbr> <wbr>by——Fudan <wbr>University

图上第一个三角形,-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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值