プログラミング思考と実践Week7の宿題(3/4 /データクラス)
A-TTの魔法の猫
ご存知のとおり、TTには魔法の猫がいます。
この日、TTは「猫とマウス」ゲームのプレイに専念しましたが、ゲームが始まる前に、スマートマジックキャットがTTゲームの最終結果を伝えました。TTは非常に驚いています。彼の子猫が実際に話しているだけでなく、なぜこのかわいい女の子がそんなに魔法なのですか。
Magic Catは、TTに、実際にはN人の個人とM人の勝敗関係を持つゲームの勝敗テーブルがあると伝えます。それぞれの勝敗関係はABであり、AがBに勝つことができ、勝敗関係は推移的です。つまり、AはBに勝ち、BはCに勝つため、AはCに勝つことができます。
TTは、子猫がどんなゲームでも予測できるとは信じていません。そのため、彼は何人の選手の結果を事前に知ることができないのか知りたいと思っています。
入力の
最初の行は、データグループの数を示します。
各データセットの最初の行は、NおよびM(N、M <= 500)を示します。
次のM行では、各行にABが与えられ、AがBに勝ることを示しています。
出力
データの各セットのためには、ゲームの結果を事前に知ることができないどのくらい決定されます。(a、b)は(b、a)と同じです。つまり、各バイナリは1回だけ計算されます。
Sample Input
3
3 3
1 2
1 3
2 3
3 2
1 2
2 3
4 2
1 2
3 4
Sample Output
0
0
4
問題分析
有向グラフを作成し、フロイトアルゴリズムを使用して方法を見つけます。
dis[i][j]
2つのポイント間の距離を表します。パスでない場合は、一定の最大整数として記録され、途中で各ポイントをトラバースして最短パスを見つけ、相互運用できないポイントをカウントします。
最適化:従来のトリプルループがタイムアウトします。2番目のレイヤーループで、iからkにウェイがあるかどうかを判断し、そうでない場合は、次のレイヤーループに直接進みます。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int INF = 0x7fffffff;
const int MAXV = 505;
int n,m;
int dis[MAXV][MAXV];
void Floyd(){
for(int k=1;k<=n;++k){
for(int i=1;i<=n;++i){
if(dis[i][k]==INF){
continue;
}
for(int j=1;j<=n;++j){
if(dis[i][k]!=INF && dis[k][j]!=INF && dis[i][k]+dis[k][j]<dis[i][j]){
dis[i][j]=dis[i][k]+dis[k][j];
}
}
}
}
}
int main()
{
int u,v,w;
int loop;
scanf("%d",&loop);
while(loop--){
scanf("%d%d",&n,&m);
fill(dis[0],dis[0]+MAXV*MAXV,INF);
for(int i=1;i<=n;++i){
dis[i][i]=0;
}
for(int i=1;i<=m;++i){
scanf("%d%d",&u,&v);
dis[u][v]=1;
}
Floyd();
int sum=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=i;++j){
if(dis[i][j]==INF&&dis[i][j]==dis[j][i]){
sum++;
}
}
}
printf("%d\n",sum);
}
return 0;
}
B-TTの旅日記
ご存知のとおり、TTには魔法の猫がいます。
今日、彼はステーションBで旅行の生放送を開始し、猫の旅中に魔法の猫との冒険を記録しました。TTは自宅を出発し、キャットエクスプレスでニャースター空港に向かう準備をしています。猫猫エクスプレスラインは、経済ラインと商業ラインに分けられ、スピードと価格が異なります。もちろん、商業路線は経済路線よりも高価ですが、TTは通常、経済路線しか利用できませんが、現在、TTの魔法の猫は商用路線チケットに変更され、商業路線を利用できます。TT送迎の時間はごくわずかであると想定して、TTがMiaoxing空港への最速ルートを見つけられるように支援してください。
入力
入力には複数のデータセットが含まれます。各データセットの最初の行は、N、S、Eの3つの整数(2≤N≤500、1≤S、E≤100)です。これは、駅、始点と終点(つまり、ニャー空港が配置されている駅)の総数です。 )番号。
次の行には、整数M(1≤M≤1000)が含まれています。これは、経済線のセクション数です。
次にM行があり、各行には3つの整数X、Y、Z(1≤X、Y≤N、1≤Z≤100)があります。これは、TTがステーションXとステーションYの間で経済的なラインを利用できることを示しています。 Z分かかります。
商業ラインの次のラインの道路セグメントの数はK(1≤K≤1000)です。
次の行Kは商業行セグメントの説明であり、形式は経済行と同じです。
すべてのセクションは双方向ですが、空港に到達するには商用チケットを使用する必要がある場合があります。最適なソリューションが一意であることを確認してください。
出力
データの各セットに対して、3行を出力します。最初の行は、TTがアクセス順に通過する駅(開始点と終了点を含む)を示します。2番目の行は、商用線へのTT転送の駅番号です(商用線のチケットが使用されていない場合は、引用符なしで「Ticket Not Used」と出力します)、3行目は、TTがニャースター空港までに費やした合計時間です。
この質問は余分なスペースとタブを無視しないので、各回答セットの間に改行が出力されます。
输入样例
4 1 4
4
1 2 2
1 3 3
2 4 4
3 4 5
1
2 4 3
输出样例
1 2 4
2
5
問題分析
商業ラインの0または1セクションしかとらないため、商業ラインを横断できます。特定の時間にIJセグメントを商業ラインとして選択し、SI、JE、またはSJ、IEセグメントが経済ライン上にあるとします。それを記録するたびに、最小値を選択できます。
経済線をとる部品の場合、ダイクストラアルゴリズムを2回使用して、開始点と終了点から他の点までの最短距離をそれぞれ記録できます。
#include <bits/stdc++.h>
using namespace std;
const int size=5e3+10;
const int N=500+5;
const int inf=0x3ffffff;
struct Edge{
int to,next,w;
}e[size];
Edge other[size];
int head[N],tot,n,vis[N],spre[N],sdis[N],tpre[N],tdis[N];
void add(int x,int y,int w)
{
e[++tot].to=y,e[tot].next=head[x];
e[tot].w=w;head[x]=tot;
}
priority_queue<pair<int,int> >q;
void dijkstra(int s,int*dis,int*pre)
{
while(!q.empty())q.pop();
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
dis[i]=inf,pre[i]=-1;
dis[s]=0;pre[s]=s;
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!=-1;i=e[i].next)
{
int y=e[i].to,w=e[i].w;
if(dis[y]>dis[x]+w)
{
dis[y]=dis[x]+w;
pre[y]=x;
q.push(make_pair(-dis[y],y));
}
}
}
}
void print(int to,int*pre)
{
if(pre[to]!=to)
{
print(pre[to],pre);
printf(" %d",to);
}
else
{
printf("%d",to);
}
}
int main() {
int s,e;
bool enter=false;
while(~scanf("%d%d%d",&n,&s,&e))
{
if(enter)
printf("\n");
enter=true;
fill(head,head+N,-1);
tot=-1;
int m;
scanf("%d",&m);
while(m--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
int k;
scanf("%d",&k);
for(int i=0;i<k;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
other[i].next=x,other[i].to=y,other[i].w=z;
}
dijkstra(s,sdis,spre);
dijkstra(e,tdis,tpre);
int point=-1,distance=sdis[e];
bool sort=true;
for(int i=0;i<k;i++)
{
if(sdis[other[i].next]+tdis[other[i].to]+other[i].w<distance)
{
distance=sdis[other[i].next]+tdis[other[i].to]+other[i].w;
point=i;sort=true;
}
if(sdis[other[i].to]+tdis[other[i].next]+other[i].w<distance)
{
distance=sdis[other[i].to]+tdis[other[i].next]+other[i].w;
point=i;sort=false;
}
}
if(point==-1)
{
print(e,spre);
}
else
{
if(sort)
{
print(other[point].next,spre);
int temp=other[point].to;
while(tpre[temp]!=temp)
{
printf(" %d",temp);
temp=tpre[temp];
}
printf(" %d",temp);
}
else
{
print(other[point].to,spre);
int temp=other[point].next;
while(tpre[temp]!=temp)
{
printf(" %d",temp);
temp=tpre[temp];
}
printf(" %d",temp);
}
}
printf("\n");
if(point==-1)
printf("Ticket Not Used\n");
else
{
if(sort)
printf("%d\n",other[point].next);
else
printf("%d\n",other[point].to);
}
printf("%d\n",distance);
}
return 0;
}
C-TTの夢
この夜、TTには甘い夢がありました!
彼の夢の中で、TTの願いが叶い、ニャースターのリーダーになりました。ニャースターには1からNまでの番号が付けられたN個の商業都市があり、そのうち1個の都市はTTが位置する都市、つまり首都です。
Meow Starには、商業都市が互いに通信するためのM方向の道路があります。しかし、Meowstarのビジネスの繁栄に伴い、一部の道路は非常に混雑しています。TTが悩んでいる間、彼の魔法のキティは解決策を思いつきました!TTは、このプログラムの新しいポリシーを受け入れ、公表します。
具体的なポリシーは次のとおりです。繁栄を示すために、各商業都市に正の整数をマークします。各猫が道路に沿って1つの商業都市から別の商業都市まで歩くとき、TTはそれらに課金します(目的地の繁栄-出発点)繁栄)^ 3税。
TTはこのポリシーが妥当かどうかをテストするつもりなので、首都から他の都市に移動するために支払う必要のある税額を知りたいと思っています。合計金額が3未満または届かない場合は、静かに「?」と入力してください。
最初の行にTを入力します。これは、Tセットのデータがあることを示します。(1 <= T <= 50)
各データセットについて、最初の行にNを入力してポイント数を示します。(1 <= N <= 200)
2行目にN個の整数を入力します。これは、1からNポイントまでの重みa [i]を表します。(0 <= a [i] <= 20)
3行目にMを入力して、有向道路の数を示します。(0 <= M <= 100000)
次のM行には、各行に2つの整数ABがあり、AからBへの方向道路があることを示しています。
次に、整数Qが与えられ、問い合わせの数を示します。(0 <= Q <= 100000)
各問い合わせはPを与えます。これは、ポイント1からポイントPまでの最小税を見つけることを意味します。
出力
各クエリは1行を出力し、到達できない場合、または税金が3未満の場合は「?」を出力します。
Sample Input
2
5
6 7 8 9 10
6
1 2
2 3
3 4
1 5
5 4
4 5
2
4
5
10
1 2 4 4 5 6 7 8 9 10
10
1 2
2 3
3 1
1 4
4 5
5 6
6 7
7 8
8 9
9 10
2
3 10
Sample Output
Case 1:
3
4
Case 2:
?
?
問題分析
最初に道路があるかどうかを確認し、道路がある場合は合計金額を計算します。
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3ffffff;
int N,M,T,Q,P;
int dis[205];
int a[100005];
int cnt[205];
int vis[205];
bool dvis[205];
struct edge{
int u_,v_,w_;
};
queue< int > q;
vector< edge > G[205];
void addE(int u,int v,int w)
{
edge e_ ; e_.u_ = u,e_.v_=v,e_.w_=w;
G[u].push_back(e_);
}
void ini()
{
for(int i=0;i<=N;i++)
{
dis[i] = inf;
vis[i] = 0;
cnt[i] = 0;
dvis[i] = 0;
}
while(!q.empty()) q.pop();
for(int i=0;i<205;i++) G[i].clear();
}
void dfs(int y)
{
dvis[y] = 1;
for(int i=0;i<G[y].size();i++)
{
y = G[y][i].v_;
if(dvis[y] == 1) continue;
dfs(y);
}
}
void spfa(int s)
{
dis[s] = 0;
vis[s] = 1;
q.push(s);
while(!q.empty())
{
int x = q.front(); q.pop();
vis[x] = 0;
for(int i=0;i<G[x].size();i++)
{
int y = G[x][i].v_ , w = G[x][i].w_;
if( dis[y] > dis[x] + w )
{
dis[y] =w + dis[x];
cnt[y] = cnt[x]+1;
if( cnt[y] >= N)
{
dfs(y);
}
if(vis[y]==1 || dvis[y]==1) continue;
vis[y] = 1;
q.push(y);
}
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin>>T;
int A,B,cost;
for(int Ti=1;Ti<=T;Ti++)
{
cin>>N;
ini();
for(int Ai=1;Ai<=N;Ai++)
{
cin>>a[Ai];
}
cin>>M;
for(int Gi=0;Gi<M;Gi++)
{
cin>>A>>B;
cost =pow( a[B]-a[A] , 3 ) ;
addE(A,B,cost);
}
spfa(1);
cin>>Q;
cout<<"Case "<<Ti<<":"<<endl;
for(int Qi=0;Qi<Q;Qi++)
{
cin>>P;
//输出最少税费
if(dvis[P] || dis[P] == inf || dis[P]<3)
{cout<<"?"<<endl;
continue;}
cout<<dis[P]<<endl;
}
}
return 0;
}