ほせいろけいかく
9881 ワード
道路工事案
時間制限:
3000 ms|メモリ制限:65535 KB
難易度:
5
説明
南将軍は多くの部隊を率いて、それらはそれぞれNの異なる都市に駐屯して、これらの都市はそれぞれ1~N番号をつけて、交通があまり便利ではないため、南将軍は道路を修理するつもりです.
今ではどの都市の間で道路を修理できるか、もし道路を修理すれば、費用はいくらですか.
今、軍師の小工はすでに道路を修理する案を見つけて、各都市をつなぐことができて、しかも費用が最も少ないです.
しかし、南将軍は、この道路工事案が綴られた図案は縁起が悪いと言っています.
入力
1行目に入力される整数T(1しゅつりょく
テストデータのセットごとにYesまたはNoを出力します(最小コストスキームが2つ以上ある場合はYesを出力し、最小コストスキームが1つしかない場合はNoを出力します)
サンプル入力
サンプル出力
問題を解く構想:費用が最も少なく、任意の2つの都市が同じであれば、最小生成ツリーが要求されることを説明する.問題の中で別の案があるかどうかを聞いて、
最小生成ツリーの効果ですので、サブ生成ツリーを使用できます
最小生成ツリーを求めた上でエッジを追加するのが一般的です
具体的な実装:primアルゴリズムを用いて最小生成ツリーを求め,任意の点から他の各点への経路上の最大エッジ重みを統計する.その後、改生成ツリーにないエッジ(u,v)を追加し、エッジを追加するとリングが形成され、
次に、このループの重み値が2つ大きいエッジ(すなわち(u,v)を除く最大重み値のエッジ)を削除し、このときの費用を再統計し、最小生成ツリーの費用と同じであれば、別のスキームがあることを示す.
次のようになります.
mp!=-1は最小生成ツリーにないエッジを表し、mx[i][j]はiからjの最大エッジを表し、主判断sum-mx[i][j]+mp[i][j]=sum
コード:
時間制限:
3000 ms|メモリ制限:65535 KB
難易度:
5
説明
南将軍は多くの部隊を率いて、それらはそれぞれNの異なる都市に駐屯して、これらの都市はそれぞれ1~N番号をつけて、交通があまり便利ではないため、南将軍は道路を修理するつもりです.
今ではどの都市の間で道路を修理できるか、もし道路を修理すれば、費用はいくらですか.
今、軍師の小工はすでに道路を修理する案を見つけて、各都市をつなぐことができて、しかも費用が最も少ないです.
しかし、南将軍は、この道路工事案が綴られた図案は縁起が悪いと言っています.
入力
1行目に入力される整数T(1
テストデータのセットごとにYesまたはNoを出力します(最小コストスキームが2つ以上ある場合はYesを出力し、最小コストスキームが1つしかない場合はNoを出力します)
サンプル入力
2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2
サンプル出力
No
Yes
: ; , , , ; ; yes
:
問題を解く構想:費用が最も少なく、任意の2つの都市が同じであれば、最小生成ツリーが要求されることを説明する.問題の中で別の案があるかどうかを聞いて、
最小生成ツリーの効果ですので、サブ生成ツリーを使用できます
最小生成ツリーを求めた上でエッジを追加するのが一般的です
具体的な実装:primアルゴリズムを用いて最小生成ツリーを求め,任意の点から他の各点への経路上の最大エッジ重みを統計する.その後、改生成ツリーにないエッジ(u,v)を追加し、エッジを追加するとリングが形成され、
次に、このループの重み値が2つ大きいエッジ(すなわち(u,v)を除く最大重み値のエッジ)を削除し、このときの費用を再統計し、最小生成ツリーの費用と同じであれば、別のスキームがあることを示す.
次のようになります.
mp!=-1は最小生成ツリーにないエッジを表し、mx[i][j]はiからjの最大エッジを表し、主判断sum-mx[i][j]+mp[i][j]=sum
コード:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int INF=0x3f3f3f3f;
#define mem(x,y) memset(x,y,sizeof(x))
#define SI(x) scanf("%d",&x)
#define PI(x) printf("%d",x)
typedef long long LL;
const int MAXN=520;
int mp[MAXN][MAXN];
int mx[MAXN][MAXN];
int vis[MAXN];
int N,sum;
vector<int>vec;
void prim(int sx){
mem(vis,0);
vis[sx]=1;
vec.push_back(sx);
int u,v;
while(vec.size()<N){
int temp=INF;
for(int i=0;i<vec.size();i++){
int x=vec[i];
// printf("%d
",x);
for(int j=1;j<=N;j++){
if(!vis[j]&&mp[x][j]!=-1){
if(temp>mp[x][j]){
temp=mp[x][j];
u=x;
v=j;
// printf("u=%d v=%d
",u,v);
}
}
}
}
for(int i=0;i<vec.size();i++){
int x=vec[i];
// printf("u=%d v=%d
",u,v);
if(mx[x][u]<mp[u][v])mx[x][v]=mx[v][x]=mp[u][v];
else mx[x][v]=mx[v][x]=mx[x][u];
}
vec.push_back(v);
vis[v]=1;
sum+=mp[u][v];
mp[u][v]=mp[v][u]=-1;
//printf("%d %d %d
",u,v,vec.size());
}
}
int main(){
int E,T;
SI(T);
int a,b,c;
while(T--){
mem(mp,-1);mem(mx,-1);
SI(N);SI(E);
while(E--){
scanf("%d%d%d",&a,&b,&c);
mp[a][b]=mp[b][a]=c;
mx[a][b]=mx[b][a]=c;
}
sum=0;
vec.clear();
prim(1);
bool ans=false;
for(int i=1;i<=N;i++){
if(ans)break;
for(int j=1;j<=N;j++){
if(mp[i][j]!=-1){
if(sum-mx[i][j]+mp[i][j]==sum){
ans=true;break;
}
// else printf("mx[%d][%d]=%d
",i,j,mx[i][j]);
}
}
}
if(ans)puts("Yes");
else puts("No");
}
return 0;
}