列表

详情


NC17357. Crossfire

描述

    袋鼠先生在玩一个塔防游戏。这个游戏中,一共有n个防御塔,第i个塔位于(xi,yi)的位置,这n个防御塔形成了一个严格的凸多边形。有m道防御网,你可以把第i道防御网看做连接第ui个防御塔和第vi个防御塔的一条线段,穿越它就需要消耗ci的血量。
    袋鼠先生想从(sx,sy)位置走到(tx,ty)位置,他想知道最少要消耗多少血量。

输入描述

第一行两个整数n, m(1≤n,m≤100,000)。接下来n行,每行包含两个整数xi,yi(|xi|,|yi|≤1,000,000,000),表示防御塔的位置,保证防御塔形成了一个严格的凸多边形,即没有三点共线,并且按逆时针顺序给出。接下来m行,每行三个整数ui,vi,ci(1≤ui,vi≤n, ui≠vi, 1≤ci≤1,000,000,000),表示每个防御网的参数。
然后接下来两行每行两个整数sx,sy和tx,ty (|sx|,|sy|,|tx|,|ty|≤1,000,000,000),保证起点和终点都不在防御网上。

输出描述

输出最少消耗的血量。

示例1

输入:

4 6
0 0
4 0
4 4
0 4
1 2 2
2 3 2
3 4 2
4 1 2
1 3 3
2 4 3
2 1
2 3

输出:

4

示例2

输入:

4 6
0 0
4 0
4 4
0 4
1 2 2
2 3 2
3 4 2
4 1 2
1 3 3
2 4 3
2 1
1 2

输出:

3

说明:

黑色表示代价为2的边,红色表示代价为3的边。
从S走到T1可以先往外走,然后从外面绕圈,然后进入T1,代价为4。
从S走到T2可以直接走,代价为3。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 88ms, 内存消耗: 22364K, 提交时间: 2018-08-13 20:55:53

#include<bits/stdc++.h>
#define maxn 1000010
#define ll long long
using namespace std;

struct pnt{
	int x,y;
}ps[maxn],s,t;
struct trt{
	int u,v,c;
}ts[maxn];
int n,m;
ll tag[2][maxn];
const ll INF=1LL<<60;
void read(int &x){
	char ch=x=0;
	bool fl=false;
	while(!isdigit(ch))
		fl|=ch=='-',ch=getchar();
	while(isdigit(ch))
		x=x*10+ch-'0',ch=getchar();
	x=fl?-x:x;
}
ll crs(pnt a,pnt b,pnt std){
	return 1LL*(a.x-std.x)*(b.y-std.y)-1LL*(a.y-std.y)*(b.x-std.x);
}
bool out(pnt tmp){
	for(int i=1;i<=n;i++){
		pnt a=ps[i],b=ps[i%n+1];
		if(crs(tmp,b,a)>0)
			return true;
	}
	return false;
}
void solve(pnt tmp,int tp){
	memset(tag[tp],0,sizeof(tag[tp]));
	for(int i=1;i<=m;i++){
		int u=ts[i].u,v=ts[i].v,c=ts[i].c;
		if(crs(ps[v],tmp,ps[u])>0)
			tag[tp][u]+=c,tag[tp][v]-=c;
		else
			tag[tp][v]+=c,tag[tp][1]+=c,tag[tp][u]-=c;
	}
	for(int i=2;i<=n;i++)
		tag[tp][i]+=tag[tp][i-1];
}
int main(){
	read(n),read(m);
	for(int i=1;i<=n;i++)
		read(ps[i].x),read(ps[i].y);
	for(int i=1;i<=m;i++){
		read(ts[i].u),read(ts[i].v),read(ts[i].c);
		if(ts[i].u>ts[i].v)
			swap(ts[i].u,ts[i].v);
	}
	read(s.x),read(s.y),read(t.x),read(t.y);
	solve(s,0),solve(t,1);
	if(out(s)&&out(t))
		puts("0");
	else if(out(s)){
		ll anst=INF;
		for(int i=1;i<=n;i++)
			anst=min(anst,tag[1][i]);
		printf("%lld\n",anst);
	}
	else if(out(t)){
		ll anss=INF;
		for(int i=1;i<=n;i++)
			anss=min(anss,tag[0][i]);
		printf("%lld\n",anss);
	}
	else{
		ll ans=0,anss=INF,anst=INF;
		for(int i=1;i<=m;i++){
			if((crs(ps[ts[i].v],s,ps[ts[i].u])>0)^(crs(ps[ts[i].v],t,ps[ts[i].u])>0))
				ans+=ts[i].c;
		}
		for(int i=1;i<=n;i++)
			anss=min(anss,tag[0][i]),anst=min(anst,tag[1][i]);
		printf("%lld\n",min(ans,anss+anst));
	}
	return 0;
}

上一题