NC17357. Crossfire
描述
输入描述
第一行两个整数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的边。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; }