【NOIP模拟】最短路
题面
小 C 终于被小 X 感动了,于是决定与他看电影,然而小 X 距离电影院非常远,现在假设每条道路需要花费小 X 的时间为 1,由于有数以万计的好朋友沿路祝贺,导致小 X在通过某些路不得不耗费 1 的时间来和他们聊天,尽管他希望尽早见到小 C,所以他希望找到一条最快时间到达电影院的路。
一开始小 X 在 1 号点,共有 N 个点,M 条路,电影院为 T 号点。
对于 30%的数据:n<=10,m<=20;
对于 60%的数据:n<=1 000,m<=20 000;
对于 100%的数据:n<=5 000 000,m<=10 000 000,1<=w<=2。
分析
因为数据是随机生成的,太弱了,于是放过了spfa(卡住了没有优化的dijkstra 23333)
但是正解其实是拆边
由于观察到边权只会是1或2,可以将其拆2的边为1和1,然后直接用bfs即可,复杂度为O(n+m)
代码
spfa+floyd(怕被卡 留点分保命)
- #include<bits/stdc++.h>
- using namespace std;
- #define N 110
- #define RT register
- #define MAXN 5000050
- int n,m,t,cnt;
- int g[N][N],d[MAXN],vis[MAXN],first[MAXN];
- queue<int>q;
- struct email
- {
- int u,v,w;
- int nxt;
- }e[MAXN*4];
- template<class T>
- inline void read(T &x)
- {
- x=0;int f=1;static char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
- x*=f;
- }
- inline void add(int u,int v,int w)
- {
- e[++cnt].nxt=first[u];first[u]=cnt;
- e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;
- }
- void spfa(int x)
- {
- memset(d,0x3f,sizeof(d));
- q.push(x);vis[x]=1;d[x]=0;
- while(!q.empty())
- {
- int u=q.front();q.pop();vis[u]=0;
- for(RT int i=first[u];i;i=e[i].nxt)
- {
- int v=e[i].v,w=e[i].w;
- if(d[v]>d[u]+w)
- {
- d[v]=d[u]+w;
- if(!vis[v])
- {
- q.push(v);
- vis[v]=1;
- }
- }
- }
- }
- }
- int main()
- {
- freopen("short.in","r",stdin);
- freopen("short.out","w",stdout);
- memset(g,0x3f,sizeof(g));
- read(n);read(m);read(t);
- if(n<=100)
- {
- for(RT int i=1;i<=m;i++)
- {
- int u,v,w;
- read(u),read(v),read(w);
- g[u][v]=g[v][u]=min(g[u][v],w);
- }
- for(RT int k=1;k<=n;k++)
- for(RT int i=1;i<=n;i++)
- for(RT int j=1;j<=n;j++)
- g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
- printf("%d\n",g[1][t]);
- return 0;
- }
- for(RT int i=1;i<=m;i++)
- {
- int u,v,w,ok=0;
- read(u),read(v),read(w);
- add(u,v,w);add(v,u,w);
- }
- spfa(1);
- printf("%d\n",d[t]);
- return 0;
- }
拆边(std)
- #include<cstdio>
- int n, m, cnt, q, num;
- int head[20000010], d[20000010], v[20000010];
- struct edge{int to, next;} e[40000010];
- void ins(int x, int y)
- {
- e[++cnt].to = y; e[cnt].next = head[x]; head[x] = cnt;
- e[++cnt].to = x; e[cnt].next = head[y]; head[y] = cnt;
- }
- char B[150 * 1024 * 1024], *S = B;
- #define getchar() (*S++)
- int read()
- {
- int x = 0; char c = getchar();
- while (c < '0' || c > '9') c = getchar();
- while (c >= '0' && c <= '9') {x = (x << 3) + (x << 1) + c - '0'; c = getchar();}
- return x;
- }
- int main()
- {
- freopen("short.in", "r", stdin);
- freopen("short.out", "w", stdout);
- int x, y, z, p, h, t, i;
- fread(B, 1, 150 * 1024 * 1024, stdin);
- n = read(); m = read(); q = read();
- num = n;
- for(i = 1; i <= m; ++i)
- {
- x = read(); y = read(); z = read();
- if(z == 1) ins(x, y);
- else ins(x, ++num), ins(num, y);
- }
- h = t = 1; d[h] = 1; v[1] = 1;
- while(h <= t)
- {
- x = d[h++];
- for(i = head[x]; i; i = e[i].next)
- if (!v[e[i].to]) {v[e[i].to] = v[x] + 1; d[++t] = e[i].to;}
- }
- printf("%d\n", v[q] - 1);
- return 0;
- }
“Make my parents proud,and impress the girl I like.”