Pro
Sol
公交车
这道题,要么点多要么边多。
正解是点多,因为我们要在公交线路上的任意两点间连一条边,这样就会产生很多的边,但是我们可以加一个虚点,向虚点连边就少很多,因为上了公交车就付一次费,所以只需要一条边有权值就好。
然后就是水的dij优化最短路。
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#define INF 1e18
using namespace std;
struct Node {
long long to , next , len;
};
Node e[1000005];
struct Que {
long long num , len;
Que(long long nn , long long dd) {
num = nn , len = dd;
}
bool operator < (const Que &a) const {
return len > a.len;
}
};
long long n , m , k , s , tot , head[200005] , dis[200005] , z[200005];
void add(long long x , long long y , long long z) {
tot++;
e[tot].next = head[x];
e[tot].to = y;
e[tot].len = z;
head[x] = tot;
}
void dij(long long x) {
priority_queue<Que>q;
for(long long i=1; i<=n; i++)
dis[i] = INF;
dis[x] = 0;
q.push(Que(x,dis[x]));
while(!q.empty()) {
Que u = q.top();
q.pop();
if(u.len != dis[u.num])
continue;
for(long long i=head[u.num]; i; i=e[i].next)
if(dis[e[i].to] > u.len + e[i].len) {
dis[e[i].to] = u.len + e[i].len;
q.push(Que(e[i].to , dis[e[i].to]));
}
}
}
int main() {
freopen("transprt.in","r",stdin);
freopen("transprt.out","w",stdout);
scanf("%lld%lld%lld%lld",&n,&m,&k,&s);
for(long long i=1; i<=m; i++) {
long long x , y , z;
scanf("%lld%lld%lld",&x,&y,&z);
add(x , y , z);
add(y , x , z);
}
for(long long i=1; i<=k; i++) {
long long x , y , z;
scanf("%lld%lld",&x,&y);
for(long long j=1; j<=y; j++) {
scanf("%lld",&z);
add(z , n+i , x);
add(n+i , z , 0);
}
}
n += k;
dij(s);
for(long long i=1; i<=n-k; i++)
printf("%lld ",dis[i]);
return 0;
}
灌溉
话说出题人真是的……两道题用到的思想差不多。
建一个虚点,虚点到各个点的距离为建水库的代价,问题就转化为:求最便宜的引水花费……
裸的MST,直接克鲁斯卡尔……
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define INF 2147483647
using namespace std;
struct Road {
int d1 , d2 , len;
bool operator < (const Road &a) const {
return len < a.len;
}
};
Road v[500005];
int n , top , val[305] , P[305][305] , fa[305] , ans;
inline int mymin(int a , int b) { return a<b?a:b; }
int find(int x) {
if(fa[x]!=x)
return find(fa[x]);
return fa[x];
}
void klus() {
int cnt = 0;
for(int i=1; i<=top; i++) {
int fx = find(v[i].d1) , fy = find(v[i].d2);
if(fx != fy) {
cnt++;
fa[fy] = fx;
ans += v[i].len;
if(cnt == n)
return ;
}
}
}
void init() {
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++) {
top++;
v[top].d1 = i;
v[top].d2 = j;
v[top].len = P[i][j];
}
for(int i=1; i<=n; i++)
fa[i] = i;
sort(v+1 , v+top+1);
}
int main() {
freopen("irrigate.in","r",stdin);
freopen("irrigate.out","w",stdout);
scanf("%d",&n);
for(int i=1; i<=n; i++) {
int x;
scanf("%d",&x);
top++;
v[top].d1 = i;
v[top].d2 = n+1;
v[top].len = x;
}
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&P[i][j]);
init();
klus();
printf("%d",ans);
return 0;
}
对决
emmm,最简单的dfs……
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Node {
int to , next;
};
Node e[200005];
int n , m , head[100005] , tot , cdu[100005] , flag[100005][3] , opt[100005] , cnt , num[100005];
void add(int x , int y) {
tot++;
e[tot].next = head[x];
e[tot].to = y;
head[x] = tot;
}
void dfs(int u , int f) {
if(opt[u]) {
flag[f][opt[u]]++;
return ;
}
for(int i=head[u]; i; i=e[i].next)
dfs(e[i].to , u);
if(flag[u][1])
opt[u] = 2;
else
opt[u] = 1;
flag[f][opt[u]]++;
}
int main() {
freopen("duel.in","r",stdin);
freopen("duel.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++) {
int x , y;
scanf("%d%d",&x,&y);
add(x , y);
cdu[x]++;
}
for(int i=1; i<=n; i++)
if(!cdu[i])
num[++cnt] = i;
sort(num+1 , num+cnt+1);
for(int i=1; i<=cnt; i++) {
int x;
scanf("%d",&x);
opt[num[i]] = x + 1;
}
for(int i=1; i<=n; i++)
if(!opt[i])
dfs(i,0);
for(int i=1; i<=n; i++) {
if(opt[i]==1)
printf("Last\n");
else
printf("First\n");
}
return 0;
}