codeforces contest 189

来源:互联网 发布:淘宝自创品牌要多少钱 编辑:程序博客网 时间:2024/05/17 02:42
http://codeforces.com/contest/189

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

D 187B AlgoRace

题意:n个城市,m辆车,r场比赛。给出m辆车在n个城市中的最短路。r场比赛给出s(起点),t(终点),k(允许换乘次数)

题解:首先预处理出m辆车在n个城市中的最短路(其实我只会用dij)。d[i][j][k]表示i到j换乘了k次。

#include <algorithm>#include <iostream>#include <cstring>#include <vector>#include <cstdio>#include <string>#include <cmath>#include <queue>#include <set>#include <map>using namespace std;typedef long long ll;#define de(x) cout << #x << "=" << x << endlint a[65][65][65],b[65][65][65],d[65][65][1005],vis[65];//s,t,kint n,m,r;void Dijkstra(int x,int y) {memset(vis,0,sizeof(vis));vis[y]=1;for(int i=1;i<=n;++i) b[x][y][i]=a[x][y][i];for(int i=1;i<n;++i) {int ans=0x3f3f3f,pos;for(int j=1;j<=n;++j) {if(!vis[j]&&b[x][y][j]<ans) {ans=b[x][y][j];pos=j;}}vis[pos]=1;for(int j=1;j<=n;++j) {if(!vis[j]&&b[x][y][pos]+a[x][pos][j]<b[x][y][j]) {b[x][y][j]=b[x][y][pos]+a[x][pos][j];}}}}int main() {    while(~scanf("%d%d%d",&n,&m,&r)) {    //第i辆车,j到k         for(int i=1;i<=m;++i) {            for(int j=1;j<=n;++j) {                for(int k=1;k<=n;++k) scanf("%d",&a[i][j][k]);            }        }        memset(b,0x3f3f3f,sizeof(b));        memset(d,0x3f3f3f,sizeof(d));        for(int i=1;i<=m;++i) {            for(int j=1;j<=n;++j) {                Dijkstra(i,j);//第i辆车,以j为起点                for(int k=1;k<=n;++k) {                    d[j][k][0]=min(d[j][k][0],b[i][j][k]);                }            }        }        //i到j换k次        for(int k=1;k<=65;++k) {            for(int i=1;i<=n;++i) {                for(int j=1;j<=n;++j) {                    for(int x=1;x<=n;++x) {                        d[i][j][k]=min(d[i][j][k],d[i][x][k-1]+d[x][j][0]);                    }                }            }        }        int x,y,z;        for(int i=1;i<=r;++i) {            scanf("%d%d%d",&x,&y,&z);            if(z>65) z=65;            printf("%d\n",d[x][y][z]);        }    }    return 0;}



//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

E 187C Weak Memory

题意:n个点,m条边,k个特殊点。起点s,终点t。有一个健忘的人要从s走到t,但是他从特殊点开始走ans个点就不走了。请问ans最小是多少。(保证起点一定是特殊点)

题解:二分答案。

#include<cstdio>#include<cstring>#include<queue>using namespace std;const int N=100005;int vol[N],last[N],sz,val[N],vis[N],in[N];struct Edge {    int pre,to;}e[4*N];void addEdge(int u,int v) {    e[++sz].to=v;    e[sz].pre=last[u];    last[u]=sz;}void initE() {    sz=0;    memset(last,-1,sizeof(last));}int n,m,k,s,t;bool check(int dis) {    memset(vis,0,sizeof(vis));//有没有被访问过     memset(val,0,sizeof(val));     memset(in,0,sizeof(in));//有没有在队列里     queue<int> que;    vis[s]=1;val[s]=dis;in[s]=1;    que.push(s);    while(!que.empty()) {        int u=que.front();que.pop();in[u]=0;        if(t==u) return 1;        for(int i=last[u];i!=-1;i=e[i].pre) {            int v=e[i].to;            if(t==v) return 1;            vis[v]=1;            int tt;            if(vol[v]) tt=dis;            else tt=val[u]-1;            if(tt>val[v]) {                val[v]=tt;                if(!in[v]) {                    que.push(v);                    in[v]=1;                }            }        }    }    return vis[t];}int main() {    while(~scanf("%d%d%d",&n,&m,&k)) {        memset(vol,0,sizeof(vol));        for(int i=1;i<=k;++i) {            int x;scanf("%d",&x);            vol[x]=1;        }        initE();int u,v;        for(int i=1;i<=m;++i) {            scanf("%d%d",&u,&v);            addEdge(u,v);            addEdge(v,u);        }        scanf("%d%d",&s,&t);        int l=1,r=n,ans=-1;        while(l<=r) {            int mid=l+r>>1;            if(check(mid)) {                ans=mid;                r=mid-1;            } else {                l=mid+1;            }        }        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击