Problem C. gCampus Google APAC 2016 University Test Round A

这一题看起来很水,结果被坑了大半天。><

解法就是把所有的点当做起点,求一次最短路。再看这些最短路上有哪些边,这些边就是就是efficient的。

最开始我用一个pre对最短路上的每个点记录其parent node,然后循环从终点推到起点就可以得出这一条最短路上有哪些边。这么做有一个问题,如果st to ed存在多条最短路,pre数组就会被覆盖掉,然后只会记录一条最短路上的边。感觉如果对每一个node内一个pre vector,然后dfs找出所有的最短路也行吧。正解是如果dis[i]+cost[i][j]=dis[j]那么边(i,j)就是在i to j的最短路上。其中dis[i]是st to i的最短路距离,cost是两个点之间的weight。

另外,这一题中两个office之间可能有多条road,这些road的cost可能相同也可能不同。所以就不能用邻接矩阵存图,因为这样两个office之间只会记录一条边。改成邻接表存图就不会有这个问题。我用邻接矩阵开始过了小数据,大数据incorrect。还以为是溢出了,最后是通过看large input data+对拍找出来的。/(ㄒoㄒ)/~~

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>

using namespace std;

//2016 Round A Problem C. gCampus
int T;
const int maxn=110;
int M;
int N;
pair<int,int>road[10010];
long long dis[maxn];//arriving time=S+distance
const long long INF=1e18;
bool vis[maxn];
bool efficient[10010];
//int edgeidx[maxn][maxn];
class node
{
public:
    int neighbor;
    int cost;
    int index;
    node()
    {
        neighbor=0;
        cost=0;
        index=0;
    }
    node(int n,int c,int i)
    {
        neighbor=n;
        cost=c;
        index=i;
    }
};
vector<node>mp[maxn];
class ComparisonClass
{
public:
    bool operator()(pair<long long,int>a,pair<long long,int>b)
    {
        if(a.first==b.first)
        {
            return a.second>b.second;//second is index
        }
        return a.first>b.first;//first is distance
    }
};
void shortest(int st)
{
    //memset(dis,0x3f,sizeof(dis));
    for(int i=0;i<N;i++)
    {
        dis[i]=INF;
    }
    memset(vis,false,sizeof(vis));
//    memset(pre,0,sizeof(pre));
    dis[st]=0;
    //pre[st]=-1;
    priority_queue<pair<long long,int>,vector<pair<long long,int> >,ComparisonClass> que;
    que.push(make_pair(0,st));
    while(!que.empty())
    {
        pair<long long,int>now=que.top();
        vis[now.second]=true;
        que.pop();
       // cout<<"cur "<<now.second<<endl;
        for(int i=0;i<mp[now.second].size();i++)
        {
            int neigh=mp[now.second][i].neighbor;
            //if(mp[now.second][i]==0) continue;
            if(vis[neigh]==true) continue;
            if(dis[neigh]>now.first+mp[now.second][i].cost)
            {
                dis[neigh]=now.first+mp[now.second][i].cost;
                //pre[i]=now.second;
                //cout<<"update "<<i<<" "<<pre[i]<<endl;
//                if(st==0&&i==2)
//                {
//                    cout<<now.second<<" "<<now.first<<" "<<mp[now.second][i]<<endl;
//                }
                pair<long long,int>tmp=make_pair(dis[neigh],neigh);
                que.push(tmp);
            }
        }
    }
//    if(st!=0) return;
//    for(int i=0;i<N;i++)
//    {
//        cout<<dis[i]<<endl;
        cout<<"ed "<<i<<" "<<dis[i]<<endl;
//    }
}
//void findallroads(int st)
//{
//    for(int ed=0;ed<N;ed++)
//    {
//        if(st==ed) continue;
//        int node=ed;
//        while(pre[node]!=-1)
//        {
//            //cout<<node<<" "<<pre[node]<<endl;
//            used.insert(make_pair(min(node,pre[node]),max(node,pre[node])));
//            node=pre[node];
//        }
//    }
//}
void findallroads()
{
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<mp[i].size();j++)
        {
            int neigh=mp[i][j].neighbor;
            if(dis[i]+mp[i][j].cost==dis[neigh])
            {
                efficient[mp[i][j].index]=true;
                //used.insert(make_pair(min(i,j),max(i,j)));
            }
        }

    }
}
int main()
{
    freopen("C-large-practice.in","r",stdin);
//    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        scanf("%d %d",&N,&M);
        memset(mp,0,sizeof(mp));
        memset(efficient,false,sizeof(efficient));
//        used.clear();
        for(int i=0;i<M;i++)
        {
            int U=0;
            int V=0;
            int C=0;
            scanf("%d %d %d",&U,&V,&C);
            mp[U].push_back(node(V,C,i));
            mp[V].push_back(node(U,C,i));
//            if(mp[U][V]==0)//(U,V) may have multiple input cost, use adjacent vector instead
//            {
//                mp[U][V]=C;
//                edgeidx[U][V]=i;
//            }
//            else
//            {
//                cout<<U<<" "<<V<<" "<<C<<" "<<mp[U][V]<<endl;
//                if(C<mp[U][V])
//                {
//                    mp[U][V]=C;
//                    edgeidx[U][V]=i;//what if (U,V) is connected by two roads with same cost?
//                }
//                //mp[U][V]=min(mp[U][V],C);
//            }
//            if(mp[V][U]==0)
//            {
//                mp[V][U]=C;
//                edgeidx[V][U]=i;
//            }
//            else
//            {
//                if(C<mp[V][U])
//                {
//                    mp[V][U]=C;
//                    edgeidx[V][U]=i;
//                }
//                //mp[V][U]=min(mp[V][U],C);
//            }
//            if(U==0&&V==2) cout<<U<<" "<<V<<" "<<mp[U][V]<<endl;
//            if(U==2&&V==0) cout<<U<<" "<<V<<" "<<mp[U][V]<<endl;
            //road[i]=make_pair(min(U,V),max(U,V));


            //set.insert(make_pair(min(U,V),max(U,V)));
        }
        //cout<<N<<endl;
        printf("Case #%d:\n",ca);
        for(int i=0;i<N;i++)
        {
            //cout<<i<<endl;
            shortest(i);
            findallroads();
        }
        //int cnt=0;
        for(int i=0;i<M;i++)
        {
            if(efficient[i]==false)
            {
                printf("%d\n",i);
            }
//            if(used.find(road[i])==used.end())
//            {
//                //ineff[cnt++]=i;
//                printf("%d\n",i);
//            }
        }

    }
    return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值