Round A APAC Test 2016 Problem C. gCampus 最短路

32 篇文章 0 订阅
24 篇文章 0 订阅

Problem C. gCampus

This contest is open for practice. You can try every problem as many times as you like, though we won't keep track of which problems you solve. Read the Quick-Start Guide to get started.
Small input
10 points
Large input
15 points
Download C-large-practice.in
your output file:
source file(s):    not needed for the practice contest
  

Problem

Company G has a main campus with N offices (numbered from 0 to N - 1) and Mbidirectional roads (numbered from 0 to M - 1). The ith road connects a pair of offices (Ui, Vi), and it takes Ci minutes to travel on it (in either direction).

A path between two offices X and Y is a series of one or more roads that starts at X and ends at Y. The time taken to travel a path is the sum of the times needed to travel each of the roads that make up the path. (It's guaranteed that there is at least one path connecting any two offices.)

Company G specializes in efficient transport solutions, but the CEO has just realized that, embarrassingly enough, its own road network may be suboptimal! She wants to know which roads in the campus are inefficient. A road is inefficient if and only if it is not included in any shortest paths between any offices.

Given the graph of offices and roads, can you help the CEO find all of the inefficient roads?

Input

The first line of the input gives the number of test cases, TT test cases follow. Each case begins with one line with two integers N and M, indicating the number of offices and roads. This is followed by M lines containing three integers each: UiVi and Ci, indicating the ith road is between office Ui and office Vi, and it takes Ci minutes to travel on it.

Output

For each test case, output one line containing "Case #x:", where x is the test case number (starting from 1). Then output the road numbers of all of the inefficient roads, in increasing order, each on its own line. (Note that road 0 refers to the first road listed in a test case, road 1 refers to the second road, etc.)

Limits

0 < Ci ≤ 1000000.

Small dataset

1 ≤ T ≤ 10.
1 ≤ N = M ≤ 100.

Large dataset

1 ≤ T ≤ 3.
1 ≤ N ≤ 100.
1 ≤ M ≤ 10000.

Sample


Input 
 

Output 
 
2
3 3
0 1 10
1 2 3
2 0 3
3 3
0 1 10
1 2 3
2 1 3
Case #1:
0
Case #2:
题意,给出一个图,要求,输出非最短路上的所有边。

直接用disjtra算法求出所有源点的最短路,如果,某个点的最短距离加上这条边正好是别一个边的最短距离,则这条边就是在最短路上的边,用了n次disjtra复杂度为o(n * n * log(n))

#define typec ll
const typec inf = 1e18;
#define E 100005
#define V 105
typec cost[E],dist[V];
int e,pnt[E],nxt[E],head[V],prev[V],vis[V],num[V],index[E];
bool Use[E];
struct qnode {
    int v,en,k;typec c;
    qnode (int vv=0,int ene = 0,typec cc=0):v(vv),en(ene),c(cc){
    }
    bool operator <(const qnode & r)const {return c>r.c;}
};
priority_queue<qnode> que;
void dijkstra(int n,const int src){
    qnode mv;
    int i,j,k,pre;
    while(!que.empty()) que.pop();
    vis[src]=1;dist[src]=0;
    que.push(qnode(src,-1,0));
    for(pre=src,i=1;i<n;i++){
        for(j=head[pre];j!=-1;j=nxt[j]){
            k=pnt[j];
            if(vis[k]==0&&
               dist[pre]+cost[j]<dist[k]){
                    dist[k]=dist[pre]+cost[j];
                    que.push(qnode(pnt[j],j,dist[k]));
                    prev[k]=pre;
               }
        }
        while(!que.empty()&&vis[que.top().v]==1){
            que.pop();
        }
        if(que.empty())break;
        mv=que.top();que.pop();
        vis[pre=mv.v]=1;
    }
    for(int i = 1;i<=n;i++){
        pre = i;
        for(j=head[pre];j!=-1;j=nxt[j]){
            k=pnt[j];
            if(dist[pre] + cost[j] == dist[k]){
                Use[index[j]] = true;
            }
        }
    }
}
inline void addedge(int u,int v,typec c,int in){
    index[e] = in;pnt[e]=v;cost[e]=c;nxt[e]=head[u];head[u]=e++;
}


int T,n,m;
int main()
{
    freopen("C-large-practice.in", "r", stdin);
    freopen("C-large-practice.out", "w", stdout);

     while(S(T)!=EOF)
    {
        For(ta,1,T+1){
            S2(n,m);
            e=0;
            memset(head,-1,sizeof(head));
            fill(Use,false);
            for(int i=0;i<m;i++){
                int s,ee,c;
                scanf("%d%d%d",&s,&ee,&c);
                s++,ee++;
                addedge(s,ee,c,i);
                addedge(ee,s,c,i);
            }
            For(i,1,n+1){
                memset(vis,0,sizeof(vis));
                memset(prev,-1,sizeof(prev));
                for(int j=0;j<=n;j++)dist[j]=inf;
                dijkstra(n,i);
            }
            printf("Case #%d:\n",ta);
            FI(m){
                if(!Use[i]){
                    printf("%d\n",i);
                }
            }
        }

    }
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值