Day1 最短路專題
文章目錄
A. POJ 3660 Cow Contest 傳遞閉包
題目
題解
這個。。。。。。不需要題解吧。
程式碼
//#include<bits/stdc++.h>
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
const int maxn=110;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int d[maxn][maxn],ans;
int main()
{
int n,m;read(n);read(m);
for (int i=1;i<=m;++i)
{
int x,y;
read(x);read(y);
d[x][y]=1;
}
for (int k=1;k<=n;++k)
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
d[i][j]|=d[i][k]&d[k][j];
for (int i=1;i<=n;++i)
{
int tot=0;
for (int j=1;j<=n;++j)
if (d[i][j] || d[j][i])
++tot;
if (tot==n-1) ++ans;
}
printf("%d\n",ans);
return 0;
}
B. UVA11374 Airport Express
題目
程式碼(AC)
#include<bits/stdc++.h>
using namespace std;
const int maxn=505,maxm=5005;
const int inf=0x3f3f3f3f;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int n,s,t;
int ver[maxn*maxm],edge[maxn*maxm],Next[maxn*maxm],head[maxn],len;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int vis[maxn],dist[2][maxn],pre[2][maxn];
inline void spfa(int flag)
{
queue<int>q;
for (int i=1;i<=n;++i)
{
dist[flag][i]=inf;
vis[i]=0;
pre[flag][i]=-1;
}
dist[flag][s]=0,vis[s]=1;
pre[flag][s]=s,q.push(s);
while (!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i],z=edge[i];
if (dist[flag][y]>dist[flag][x]+z)
{
dist[flag][y]=dist[flag][x]+z;
pre[flag][y]=x;
if (!vis[y]) q.push(y),vis[y]=1;
}
}
}
}
inline void input()
{
int num;
read(num);
for (int i=1;i<=num;++i)
{
int a,b,c;
read(a);read(b);read(c);
add(a,b,c),add(b,a,c);
}
}
inline void print(int x)
{
if (pre[0][x]==x)
{
printf("%d",x);//多打了個空格
return ;
}
print(pre[0][x]);
printf(" %d",x);
}
inline void solve()
{
int num,minum=dist[0][s],tu=-1,tv=-1;
read(num);
for (int i=1;i<=num;++i)
{
int a,b,c;
read(a);read(b);read(c);
if (dist[0][a]+dist[1][b]+c<minum)
{
minum=dist[0][a]+dist[1][b]+c;
tu=a,tv=b;
}
if (dist[0][b]+dist[1][a]+c<minum)
{
minum=dist[0][b]+dist[1][a]+c;
tu=b,tv=a;
}
}
if (tu==-1)
{
print(s);
puts("");
puts("Ticket Not Used");
}
else
{
print(tu);
for (int i=tv;i!=s;i=pre[1][i])
printf(" %d",i);//打成了printf(" %d,i");好無語
printf(" %d\n",s);
printf("%d\n",tu);
}
printf("%d\n",minum);
}
int main()
{
int cnt=1;
while (scanf("%d %d %d",&n,&s,&t)==3)
{
memset(head,0,sizeof(head));
if (cnt!=1) puts("");
++cnt;
input();
spfa(0);
s=t;
spfa(1);
solve();
}
return 0;
}
C.BZOJ 4152: [AMPPZ2014]The Captain
題目
題解
先說下做法:
1.對於一個點,我們記錄他的位置,橫座標c,縱座標。
2.先將點的橫座標從小到大排序,然後每兩個點建圖,然後縱座標亦然。
3.跑一遍模板,輸出即可。
程式碼
//#include<bits/stdc++.h>
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
#define pii pair<long long,int>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
struct Orz
{
int id,x,y;
}h[maxn];
inline bool mycpy1(Orz a,Orz b)
{
return a.x<b.x;
}
inline bool mycpy2(Orz a,Orz b)
{
return a.y<b.y;
}
int ver[maxn<<2],Next[maxn<<2],head[maxn],len;
ll edge[maxn<<2];
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
ll dist[maxn];
bool vis[maxn];
inline void dijkstra_heap(int s)
{
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
priority_queue<pii,vector<pii>,greater<pii> >q;
dist[s]=0;
q.push(make_pair(0,s));
while (!q.empty())
{
int x=q.top().second;
q.pop();
if (vis[x]) continue;
vis[x]=1;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i],z=edge[i];
if (dist[y]>dist[x]+z)
{
dist[y]=dist[x]+z;
q.push(make_pair(dist[y],y));
}
}
}
}
int main()
{
int n;read(n);
for (int i=1;i<=n;++i)
read(h[i].x),read(h[i].y),h[i].id=i;
sort(h+1,h+n+1,mycpy1);
for (int i=1;i<n;++i)
add(h[i].id,h[i+1].id,h[i+1].x-h[i].x),add(h[i+1].id,h[i].id,h[i+1].x-h[i].x);
sort(h+1,h+n+1,mycpy2);
for (int i=1;i<n;++i)
add(h[i].id,h[i+1].id,h[i+1].y-h[i].y),add(h[i+1].id,h[i].id,h[i+1].y-h[i].y);
dijkstra_heap(1);
printf("%lld\n",dist[n]);
return 0;
}
D. UVA10603 倒水問題 Fill
題目
題解
首先由於沒有刻度,如果用數學方法計算,不好算,樣例還好算一點,我們觀察那個都不大於,挺小的,適合暴力求解。
就是把所有情況都倒一次,倒水就兩種倒法,要麼把一個杯子倒滿,要麼就是這個杯子空了,由於水量是固定的,那麼確定兩個杯子的水量,那麼第三個也就確定了,所以我們用二維陣列進行標記,我記的是前兩個杯子(記任意兩個都行)。
由於要求是倒水題最少,而不是步數最少,首先它們沒有必要的關係,並不是步數少,倒水題就少,所以我們採用優先佇列,倒水量少的優先,那麼倒到時,倒水量一定是最少的,
然後就是,把所有的情況都找一下,如果找到及時退出,找不到找比小並且最近的即可。
注意標記的時候,不要標記錯,我第一次標記錯了,不是標記,而是固定的數。
摘自dwtfukgv。
程式碼
#include<bits/stdc++.h>
using namespace std;
const int maxn=205;
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
struct orz
{
int val[3],d;
bool operator < (const orz &tmp) const
{
return d>tmp.d;
}
};
int ans[maxn];
bool vis[maxn][maxn];
inline void update(orz x)//及時更新倒水量
{
for (int i=0;i<3;++i)
{
int y=x.val[i];
if (ans[y]<0 || ans[y]>x.d) ans[y]=x.d;
}
}
inline void bfs(int a,int b,int c,int d)
{
int cap[]={a,b,c};//容量大小
memset(ans,-1,sizeof(ans));
memset(vis,0,sizeof(vis));
priority_queue<orz>q;
orz x;
x.val[0]=0,x.val[1]=0;//開始的狀態
x.val[2]=c,x.d=0;
q.push(x);
vis[0][0]=1;
while (!q.empty())
{
x=q.top();
q.pop();
update(x);
if (ans[d]>=0) break;//找到d了 及時退出
for (int i=0;i<3;++i)
for (int j=0;j<3;++j)
{
if (i==j || !x.val[i] || x.val[j]==cap[j]) continue;//i是空的,或者j是已經滿了
orz y;
memcpy(&y,&x,sizeof(x));
int t=min(cap[j]-y.val[j],y.val[i]);//找倒水量,要麼倒滿,要麼倒空
y.val[i]-=t;
y.val[j]+=t;
y.d+=t;
if (vis[y.val[0]][y.val[1]]) continue;
vis[y.val[0]][y.val[1]]=1;
q.push(y);
}
}
for ( ;d>=0;--d)//找最近的
if (ans[d]>=0)
{
printf("%d %d\n",ans[d],d);
return ;
}
}
int main()
{
int t;read(t);
while (t--)
{
int a,b,c,d;
read(a);read(b);
read(c);read(d);
bfs(a,b,c,d);
}
return 0;
}
E. BZOJ 2662: [BeiJing wc2012]凍結 分層圖
題目
錯誤原因
兩份程式碼唯一的不同就是maxn的大小,AC的maxn是1e6+10,TLE的maxn是1e7+10。
程式碼
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxn<<1],edge[maxn<<1],Next[maxn<<1],head[maxn],len;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int dist[maxn];
bool vis[maxn];
inline void spfa(int s)
{
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
queue<int>q;
dist[s]=0,vis[s]=1;
q.push(s);
while (!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i],z=edge[i];
if (dist[y]>dist[x]+z)
{
dist[y]=dist[x]+z;
if (!vis[y]) q.push(y),vis[y]=1;
}
}
}
}
int main()
{
int n,m,k;
read(n);read(m);read(k);
for (int i=1;i<=m;++i)
{
int x,y,z;
read(x);read(y);read(z);
add(x,y,z);add(y,x,z);
for (int j=0;j<=k;++j)
{
add(x+j*n,y+j*n,z);
add(y+j*n,x+j*n,z);
add(x+j*n,y+(j+1)*n,z>>1);
add(y+j*n,x+(j+1)*n,z>>1);
}
}
spfa(1);
int ans=0x3f3f3f3f;
for (int i=0;i<=k;++i)
ans=min(ans,dist[n*(i+1)]);
printf("%d\n",ans);
return 0;
}
雙倍經驗:
BZOJ 2763: [JLOI2011]飛行路線
錯誤原因
陣列範圍真是一門學問,開大了還會TLE。。。。。。。。。
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int maxn=11e4+10,maxm=125e4+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxm<<1],edge[maxm<<1],Next[maxm<<1],head[maxn],len;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int dist[maxn];
bool vis[maxn];
inline void Dijkstra(int s)
{
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
priority_queue<pii,vector<pii>,greater<pii> >q;
dist[s]=0;
q.push(make_pair(0,s));
while (!q.empty())
{
int x=q.top().second;
q.pop();
if (vis[x]) continue;
vis[x]=1;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i],z=edge[i];
if (dist[y]>dist[x]+z)
{
dist[y]=dist[x]+z;
q.push(make_pair(dist[y],y));
}
}
}
}
int main()
{
int n,m,k,st,ed;
read(n);read(m);read(k);
read(st);read(ed);
for (int i=1;i<=m;++i)
{
int x,y,z;
read(x);read(y);read(z);
add(x,y,z);add(y,x,z);
for (int j=1;j<=k;++j)
{
add(x+(j-1)*n,y+j*n,0);//相當於使用了一個卡片,從這一層向另一層連一條邊
add(y+(j-1)*n,x+j*n,0);
add(x+j*n,y+j*n,z);
add(y+j*n,x+j*n,z);
}
}
for (int i=1;i<=k;++i)
add(ed+(i-1)*n,ed+i*n,0);
Dijkstra(st);
printf("%d\n",dist[ed+k*n]);
return 0;
}
三倍經驗
[USACO09FEB]改造路Revamping Trails
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int maxm=21e5+10,maxn=22e4+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxm<<1],edge[maxm<<1],Next[maxm<<1],head[maxn],len;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int dist[maxn];bool vis[maxn];
inline void Dijkstra(int s)
{
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
priority_queue<pii,vector<pii>,greater<pii> >q;
dist[s]=0;
q.push(make_pair(0,s));
while (!q.empty())
{
int x=q.top().second;
q.pop();
if (vis[x]) continue;
vis[x]=1;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i],z=edge[i];
if (dist[y]>dist[x]+z)
{
dist[y]=dist[x]+z;
q.push(make_pair(dist[y],y));
}
}
}
}
int main()
{
int n,m,k;
read(n);read(m);read(k);
for (int i=1;i<=m;++i)
{
int x,y,z;
read(x);read(y);read(z);
add(x,y,z);add(y,x,z);
for (int j=1;j<=k;++j)
{
add(x+j*n,y+j*n,z);
add(y+j*n,x+j*n,z);
add(x+(j-1)*n,y+j*n,0);
add(y+(j-1)*n,x+j*n,0);
}
}
int tmp=n;
Dijkstra(1);
int ans=dist[tmp];
for (int i=1;i<=k;++i)
ans=min(ans,dist[n*i+tmp]);
printf("%d\n",ans);
return 0;
}
F. BZOJ 2118 墨墨的等式 數論建圖
題目
題解
首先,隆重推出這位大佬BerryKanry,大佬看後都說這位講的不錯,所以,題解什麼的,就省略了。。
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int n;
ll ql,qr,maxmum=0x3f3f3f3f3f3f3f3fll;
ll a[maxn],dist[maxn],vis[maxn];
inline void spfa()
{
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
queue<int>q;
dist[0]=0,vis[0]=1;
q.push(0);
while (!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for (int i=1;i<=n;++i)
{
int y=(x+a[i])%maxmum;
if (dist[y]>dist[x]+a[i])
{
dist[y]=dist[x]+a[i];
if (!vis[y]) q.push(y),vis[y]=1;
}
}
}
}
inline ll query(ll x)
{
ll ans=0;
for (int i=0;i<maxmum;++i)
if (dist[i]<=x)
ans+=(x-dist[i])/maxmum+1;
return ans;
}
int main()
{
read(n);read(ql);read(qr);
for (int i=1;i<=n;++i)
{
read(a[i]);
if (!a[i])
{
--i,--n;
continue;
}
maxmum=min(maxmum,a[i]);
}
spfa();
printf("%lld\n",query(qr)-query(ql-1));
return 0;
}
相關文章
- 單/全最短路專題 兩題
- 最短路:求最長最短路
- 最短路 || 最長路 || 次短路
- 2020複習專題——最短路
- 最短路專項
- 自專案Day1
- 最短路徑問題
- 國慶day1補題
- Offer68題 Day1
- 單源最短路問題
- LeetCode刷題記錄——day1LeetCode
- 【刷題打卡】day1 - 字串string字串
- HNOI2019 DAY1 題解
- 團隊專案衝刺--day1
- HDU - 3790 (雙標準限制最短路徑)最短路徑問題
- 團隊專案Scrum衝刺day1Scrum
- 團隊專案Scrum衝刺-day1Scrum
- 學成線上專案總結 - Day1
- [IOI2018]-day1 簡要題解
- P1354 房間最短路問題
- 最短路徑問題 (dijkstra演算法)演算法
- 九度oj-最短路徑問題
- day1
- week2 kuangbin 題單 最短路問題 + 並查集問題並查集
- Python Day1Python
- 最短路
- 次短路
- Luogu P10869 LCMs 題解 [ 黃 ] [ lcm ] [ 最短路 ]
- [筆記](更新中)最短路問題的變形筆記
- 圖論最短路徑問題與matlab實現圖論Matlab
- 圖的最短路徑問題 詳細分解版
- bellman-ford 單源最短路問題 圖解圖解
- 最大值(最短路+最短路計數)
- 【CH Round #48 - Streaming #3(NOIP模擬賽Day1)】 題解
- Learning Java day1Java
- Laravel 框架 day1Laravel框架
- 使用A*演算法解迷宮最短路徑問題演算法
- 2024_4_22 路徑花費為最長$k$條邊之和最短路