Day9 圖論綜合題
A. 白銀蓮花池
題目
程式碼
#include<bits/stdc++.h>
using namespace std;
const int maxn=35;
const int maxm=1e5+10;
const int dx[8]={1,2,2,1,-1,-2,-2,-1};
const int dy[8]={2,1,-1,-2,-2,-1,1,2};
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(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,m,sx,sy,tx,ty;
char c[maxn][maxn];
int ver[maxm<<1][2],edge[maxm<<1],Next[maxm<<1],head[maxn][maxn],len;
inline void add(int x,int y)
{
for (int i=0;i<8;++i)
{
int xx=x+dx[i],yy=y+dy[i];
if (xx>0 && xx<=n && yy>0 && yy<=m)
{
if (c[xx][yy]=='0')
ver[++len][0]=xx,ver[len][1]=yy,edge[len]=1,Next[len]=head[x][y],head[x][y]=len;
else if (c[xx][yy]=='1' || c[xx][yy]=='4')
ver[++len][0]=xx,ver[len][1]=yy,edge[len]=0,Next[len]=head[x][y],head[x][y]=len;
}
}
}
int dist[maxn][maxn],step[maxn][maxn];
bool vis[maxn][maxn];
long long ans[maxn][maxn];
inline void spfa()
{
memset(dist,0x3f3f3f,sizeof(dist));
memset(step,0x3f3f3f,sizeof(step));
queue<pair<int,int> >q;
dist[sx][sy]=0,step[sx][sy]=0,ans[sx][sy]=1;
q.push(make_pair(sx,sy));
while (!q.empty())
{
int ux=q.front().first,uy=q.front().second;
q.pop();
vis[ux][uy]=0;
for (int i=head[ux][uy];i;i=Next[i])
{
int vx=ver[i][0],vy=ver[i][1];
if (dist[vx][vy]>dist[ux][uy]+edge[i])
{
dist[vx][vy]=dist[ux][uy]+edge[i];
step[vx][vy]=step[ux][uy]+1;
ans[vx][vy]=ans[ux][uy];
if (!vis[vx][vy]) q.push(make_pair(vx,vy)),vis[vx][vy]=1;
}
else if (dist[vx][vy]==dist[ux][uy]+edge[i])
{
if (step[vx][vy]>step[ux][uy]+1)
{
step[vx][vy]=step[ux][uy]+1;
ans[vx][vy]=ans[ux][uy];
if (!vis[vx][vy]) q.push(make_pair(vx,vy)),vis[vx][vy]=1;
}
else if (step[vx][vy]==step[ux][uy]+1)
ans[vx][vy]+=ans[ux][uy];
}
}
}
}
int main()
{
freopen("silvlily.in","r",stdin);
freopen("silvlily.out","w",stdout);
read(n);read(m);
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
{
cin>>c[i][j];
if (c[i][j]=='3') sx=i,sy=j;
if (c[i][j]=='4') tx=i,ty=j;
}
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)//錯誤原因1
if (c[i][j]!='2')
add(i,j);
spfa();
if (dist[tx][ty]==1061109567)
puts("-1");
else
printf("%d\n%d\n%lld",dist[tx][ty],step[tx][ty],ans[tx][ty]);
return 0;
}
B. 跳樓機
題目
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(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],Next[maxn<<1],head[maxn],len;
ll edge[maxn<<1];
inline void add(int x,int y,ll z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
ll dist[maxn];
bool vis[maxn];
inline void spfa(int s)
{
memset(dist,0x3f3f3f3f,sizeof(dist));
memset(vis,0,sizeof(vis));
queue<int>q;
// dist[1%s]=1,vis[1%s]=1;
// q.push(1%s);
dist[1]=1,vis[1]=1;//一樓能到的mod x最小樓層數就是1了,所以dist[1]=1,zz的錯誤
q.push(1);
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];
ll 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()
{
freopen("srwudi.in","r",stdin);
freopen("srwudi.out","w",stdout);
ll h;int x,y,z;
read(h);read(x);read(y);read(z);
if (x==1 || y==1 || z==1)
{
printf("%lld\n",h);
exit(0);
}
for (int i=0;i<x;++i)
add(i,(i+y)%x,y),add(i,(i+z)%x,z);
spfa(1);
ll ans=0;
for (int i=0;i<x;++i)
if (dist[i]<=h)
ans+=(h-dist[i])/x+1;
printf("%lld\n",ans);
return 0;
}
C. [中山市選]生成樹
題目
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=2007;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch)) ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
inline ll Quick_mul(ll x,ll y)
{
return ((x*y-(ll)(((long double)x*y+0.5)/mod)*mod)%mod+mod)%mod;
}
inline ll Quick_power(ll a,ll b)
{
ll ans=1;
while (b)
{
if (b&1)
ans=Quick_mul(ans,a);
a=Quick_mul(a,a);
b>>=1;
}
return ans;
}
int main()
{
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
int t;read(t);
while (t--)
{
int n;read(n);
if (n==1) puts("5");
else
{
ll ans=Quick_power(5,n-1);
printf("%lld\n",ans*n*4%mod);
}
}
return 0;
}
D. 最小代價
題目
題目描述
給出一幅由n個點m條邊構成的無向帶權圖。 其中有些點是黑點,其他點是白點。
現在每個白點都要與他距離最近的黑點通過最短路連線(如果有很多個黑點,可以選取其中任意一個),我們想要使得花費的代價最小。
請問這個最小代價是多少?
注意:最後選出的邊保證每個白點到離它最近的黑點的距離仍然等於原圖中的最短距離。
輸入格式
第一行兩個整數n,m;
第二行n 個整數,0表示白點,1 表示黑點;
接下來m 行,每行三個整數x,y,z,表示一條連線x和y 點,權值為z 的邊。
輸出格式
如果無解,輸出impossible;
否則,輸出最小代價。
樣例資料
input
5 7
0 1 0 1 0
1 2 11
1 3 1
1 5 17
2 3 1
3 5 18
4 5 3
2 4 5
output
5
【樣例解釋】
選 2、4、6三條邊
資料規模與約定
對30%的輸入資料: 1≤n≤10, 1≤m≤20; 對100%的輸入資料:1≤n≤100000,1≤m≤200000,1≤z≤1000000000
時間限制:1s1s
空間限制:256MB
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch)) ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
struct Edge
{
int x,y,z,Next,flag;
}e[maxn<<5];
int head[maxn],len,n,m,start;
inline void add(int x,int y,int z)
{
e[++len].x=x,e[len].y=y,e[len].z=z,e[len].Next=head[x],e[len].flag=0,head[x]=len;
}
ll dist[maxn];
bool vis[maxn];
inline void spfa(int s)
{
memset(dist,0x3f3f3f3f,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=e[i].Next)
{
int y=e[i].y,z=e[i].z;
if (dist[y]>dist[x]+1ll*z)
{
dist[y]=dist[x]+z;
if (!vis[y]) q.push(y),vis[y]=1;
}
}
}
}
int a[maxn];
inline void build()
{
for (int x=1;x<=n;++x)
{
if (a[x]) continue;
for (int i=head[x];i;i=e[i].Next)
{
int y=e[i].y,z=e[i].z;
if (!y) continue;
if (dist[y]+1ll*z==dist[x]) e[i].flag=1;
}
}
}
int fa[maxn];
inline int get(int x)
{
if (fa[x]==x) return x;
return fa[x]=get(fa[x]);
}
inline bool cmp(Edge a,Edge b)
{
return a.z<b.z;
}
int main()
{
freopen("minimum.in","r",stdin);
freopen("minimum.out","w",stdout);
read(n);read(m);
for (int i=1;i<=n;++i)
read(a[i]);
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 i=1;i<=n;++i)
{
if (a[i]) add(start,i,0),add(i,start,0);
fa[i]=i;
}
spfa(start);
build();
sort(e+1,e+len+1,cmp);
ll ans=0;
int tot=0;
for (int i=1;i<=len;++i)
{
if (!e[i].flag) continue;
int x=get(e[i].x),y=get(e[i].y);
if (x!=y)
{
fa[y]=x;
ans+=1ll*e[i].z;
++tot;
if (tot==n-1) break;
}
}
if (!ans)
puts("impossible");
else
printf("%lld\n",ans);
return 0;
}
E.追捕盜賊
題目
題目描述
為了幫助警察抓住在逃的罪犯,你發明了一個新的計算機系統。
警察控制的區域有N個城市,城市之間有E條雙向邊連線,城市編號為1到N。
警察經常想在罪犯從一個城市逃亡另一個城市的過程中抓住他。偵查員在仔細研究地圖,以決定在哪個城市設定障礙,或者斷掉某條路。
你的計算機系統必須回答以下兩種問題:
1、 如果連線城市G1和G2的路被封掉,罪犯能否從城市A逃到城市B?
2、 如果城市C被封掉,罪犯能否從城市A逃到城市B?
輸入格式
輸入第一行包含兩個整數N和E(2<=N<=100000,1<=E<=500000),表示城市和邊的數量。
接下來E行,每行包含兩個不同的整數Ai和Bi,表示城市Ai和Bi之間有一條邊直接相連,任意兩個城市之間最多隻有一條邊相連。
接下來一行包含一個整數Q(1<=Q<=300000),表示詢問次數。
接下來Q行,每行包含4個或5個整數,第一個數為1或2,表示詢問問題的種類。
如果問題種類是1,後面跟著4個整數A,B,G1,G2,如上描述表示詢問如果G1和G2之間的路封掉罪犯能否從城市A逃到城市B,保證A和B不同,G1和G2之間一定存在路。
如果問題種類是2,後面跟著三個整數A,B,C,三個數互不相同,表示詢問如果封掉城市C,罪犯能否從城市A逃到城市B。
輸入資料保證一開始任意兩個城市都可以相互到達。
輸出格式
每個詢問輸出一行“yes”或“no”。
樣例資料
input
13 15
1 2
2 3
3 5
2 4
4 6
2 6
1 4
1 7
7 8
7 9
7 10
8 11
8 12
9 12
12 13
5
1 5 13 1 2
1 6 2 1 4
1 13 6 7 8
2 13 6 7
2 13 6 8
output
yes
yes
yes
no
yes
資料規模與約定
時間限制:1s1s
空間限制:256MB
程式碼
#include<bits/stdc++.h>
#define YES { printf("yes\n"); continue; }//YES表示聯通
#define NO { printf("no\n"); continue; }//NO表示不聯通
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;//表示某個A或B。tmp.first表示第幾個操作,mtp.second表示是A(0)還是B(1)
const int maxn=1e5+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch)) ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int A[maxn*3],B[maxn*3],C[maxn*3],D[maxn*3],ya[maxn*3],yb[maxn*3];
int ver[maxn<<5],Next[maxn<<5],head[maxn],len;
inline void add(int x,int y)
{
ver[++len]=y,Next[len]=head[x],head[x]=len;
}
int dfn[maxn],low[maxn],id;
int fa[maxn],Q[maxn];
vector<int>b[2][maxn];//b[0][x]表示所有在點x的A的i(即它是第幾個操作),b[1][x]表示在點x的B的i
vector<pii>belc[maxn];//bC[x]表示所有以點x為C的操作
inline int tarjan(int x)
{
for (int j=0;j<=1;++j)//j=0時是A,j=1時使B
while (!b[j][x].empty())//看看所有在點x的A或B
{
int i=b[j][x].back();
if (dfn[C[i]])//必須要判斷,因為dfn[C[i]]>0了C[i]才有可能是x的祖先
belc[C[i]].push_back(make_pair(i,j));
b[j][x].pop_back();
}
dfn[x]=low[x]=++id;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i];
if (y!=fa[x])//求雙聯通分量不能重複經過某條邊
{
if (!dfn[y])
{
fa[y]=x;
tarjan(y);
low[x]=min(low[x],low[y]);
while (!belc[x].empty())//清理x的棧
{
pii tmp=belc[x].back();
tmp.second?yb[tmp.first]=y:ya[tmp.first]=y;//t.se=1則表示t是個B,否則是個A
belc[x].pop_back();
}
}
else
low[x]=min(low[x],dfn[y]);
}
}
Q[x]=id;//計算x的子樹範圍
}
inline bool in(int x,int y)//判斷點x是否在點y的子樹中
{
return dfn[y]<=dfn[x] && dfn[x]<=Q[y];
}
int type[maxn*3];
int main()
{
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
int n,m;
read(n);read(m);
for (int i=1;i<=m;++i)
{
int x,y;
read(x);read(y);
add(x,y);add(y,x);
}
int q;
read(q);
for (int i=1;i<=q;++i)
{
read(type[i]);read(A[i]);read(B[i]);read(C[i]);
if (type[i]==1) read(D[i]);
else
b[0][A[i]].push_back(i),b[1][B[i]].push_back(i);//將每個A、B存進圖中
}
for (int i=1;i<=n;++i)
if (!dfn[i]) tarjan(i);
for (int i=1;i<=q;++i)
{
if (type[i]==1)
{
if (C[i]==D[i]) YES;
if (dfn[C[i]]>dfn[D[i]]) swap(C[i],D[i]);
if (low[D[i]]==dfn[D[i]])
{
if (in(A[i],D[i]) && !in(B[i],D[i])) NO;
if (in(B[i],D[i]) && !in(A[i],D[i])) NO;
}
YES;
}
if (ya[i]==yb[i]) YES;
if (ya[i] && low[ya[i]]>=dfn[C[i]]) NO;
if (yb[i] && low[yb[i]]>=dfn[C[i]]) NO;
YES;
}
return 0;
}
相關文章
- 圖論題單圖論
- 丘奇-圖靈論題圖靈
- Day9:html和cssHTMLCSS
- day9資料解析
- 【轉載】POJ 圖論題目圖論
- Python學習DAY9Python
- 【題解】Solution Set - NOIP2024集訓Day9 樹上問題
- 繪圖、手勢綜合App繪圖APP
- 05-論證基礎:綜合運用
- 『dfn、樹剖雜項』Day9
- Steam教育在新時代中綜合學習論
- 圖論圖論
- 【圖論】-橋-並查集(1)題目描述圖論並查集
- create-react-app綜合問題ReactAPP
- 圖論 最小生成樹問題(最優連線問題)圖論
- 【模板】圖論圖論
- 模板 - 圖論圖論
- 圖論板子圖論
- 圖論最短路徑問題與matlab實現圖論Matlab
- StarCitizen星際公民載具大小比例圖綜合
- 基礎圖論圖論
- 圖論(Graph Theory)圖論Graph Theory
- CQNK圖論 1圖論
- 片 - 圖論 - 1圖論
- 圖論連通性圖論
- 最短路圖論圖論
- 【圖論】尤拉圖圖論
- 圖論筆記圖論筆記
- 圖論總結圖論
- 圖論基礎圖論
- 「過程詳解」async await綜合題AI
- 「日常訓練」「小專題·圖論」 Frogger (1-1)圖論
- 「日常訓練」「小專題·圖論」Domino Effect(1-5)圖論
- 圖論-有向圖縮點圖論
- ¡Hola Euler! 圖資料庫的理論基礎:圖論資料庫圖論
- 前端面試題總結——綜合問題(持續更新中)前端面試題
- 【面試必備】常見Java面試題大綜合Java面試題
- iOS開發常見問題之綜合篇iOS