题 意 : 给 定 一 个 无 向 图 : n 个 城 市 , 其 中 有 k 个 城 市 h i 可 以 作 为 避 难 所 题意:给定一个无向图:n个城市,其中有k个城市h_i可以作为避难所 题意:给定一个无向图:n个城市,其中有k个城市hi可以作为避难所
每 个 城 市 有 p i 个 人 , 每 个 避 难 所 能 接 纳 的 人 为 c i , 现 在 问 n 个 城 市 的 所 有 人 每个城市有p_i个人,每个避难所能接纳的人为c_i,现在问n个城市的所有人 每个城市有pi个人,每个避难所能接纳的人为ci,现在问n个城市的所有人
到 达 避 难 所 的 最 大 时 间 最 小 为 多 少 到达避难所的最大时间最小为多少 到达避难所的最大时间最小为多少
分 析 : 很 明 显 , 二 分 最 大 流 , 那 么 , 怎 么 建 图 呢 , 经 过 分析:很明显,二分最大流,那么,怎么建图呢,经过 分析:很明显,二分最大流,那么,怎么建图呢,经过 这一题
的 启 发 , 我 们 可 以 先 预 处 理 出 每 一 个 h i 到 各 个 城 市 的 最 短 时 间 的启发,我们可以先预处理出每一个h_i到各个城市的最短时间 的启发,我们可以先预处理出每一个hi到各个城市的最短时间
其 实 就 是 每 个 城 市 s i 到 避 难 所 h i 的 最 短 时 间 , 然 后 呢 , 二 分 最 短 时 间 其实就是每个城市s_i到避难所h_i的最短时间,然后呢,二分最短时间 其实就是每个城市si到避难所hi的最短时间,然后呢,二分最短时间
对 于 每 个 城 市 , 我 们 不 能 直 接 往 避 难 所 建 一 条 边 跑 最 大 流 , 这 显 然 会 T 对于每个城市,我们不能直接往避难所建一条边跑最大流,这显然会T 对于每个城市,我们不能直接往避难所建一条边跑最大流,这显然会T
怎 么 优 化 呢 , 我 们 发 现 k 值 很 小 , 那 么 对 于 每 个 城 市 最 多 有 2 k 种 状 态 怎么优化呢,我们发现k值很小,那么对于每个城市最多有2^k种状态 怎么优化呢,我们发现k值很小,那么对于每个城市最多有2k种状态
但 n 很 大 , 显 然 , 有 很 多 城 市 的 状 态 是 相 同 的 , 这 样 就 可 以 把 每 个 状 态 但n很大,显然,有很多城市的状态是相同的,这样就可以把每个状态 但n很大,显然,有很多城市的状态是相同的,这样就可以把每个状态
相 同 的 城 市 合 并 成 一 条 边 . . . 相同的城市合并成一条边... 相同的城市合并成一条边...
c o d e : code: code:
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <bitset>
#include <vector>
#include<cstring>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
typedef unsigned long long ull;
#define Ios() ios::sync_with_stdio(false);
inline int read(){int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
const int N = 3e6+5;
const int maxn = 1e5+10;
int head[maxn],tot;
struct E{
int to,next; ll val;
}e[N],ee[N];
class Max_Flow
{
public:
int s,t;
int tot,head[maxn],dep[maxn],cur[maxn];
Max_Flow(){tot=0;memset(head,-1,sizeof(head));}
void clear(){tot=0;memset(head,-1,sizeof(head));}
void add_e(int u,int v,ll w){
e[tot].to=v,e[tot].next=head[u],e[tot].val=w;
head[u]=tot++;
e[tot].to=u,e[tot].next=head[v],e[tot].val=0;
head[v]=tot++;
}
bool bfs(int S,int T){
for(int i=0;i<maxn;i++) dep[i]=0,cur[i]=head[i];
queue<int>q; q.push(S);
dep[S]=1;
while (!q.empty()){
int x=q.front(); q.pop();
for(int i=head[x];i!=-1;i=e[i].next){
int y=e[i].to;
if(dep[y]||!e[i].val) continue;
dep[y]=dep[x]+1;
q.push(y);
}
}
return dep[T];
}
ll dfs(int x,int T,ll In){
if(x==T) return In;
ll Out=0;
for(int i=cur[x];i!=-1;i=e[i].next){
int y=e[i].to; cur[x]=i;
if(dep[y]!=dep[x]+1||!e[i].val) continue;
ll res=dfs(y,T,min(e[i].val,In-Out));
e[i].val-=res,e[i^1].val+=res;
Out+=res;
if(In==Out) return Out;
}
if(In!=Out) dep[x]=0;
return Out;
}
ll Dinic(){
ll ans=0;
while (bfs(s,t)) ans+=dfs(s,t,1e16);
return ans;
}
};
bool vis[maxn];
ll dis[20][maxn];
struct node{
ll dis; int pos;
bool operator<(const node &x)const{
return x.dis<dis;
}
};
int n,m,k;
ll a[maxn],h[maxn],c[maxn];
void add_e(int u,int v,ll w){
ee[tot]={v,head[u],w};
head[u]=tot++;
ee[tot]={u,head[v],w};
head[v]=tot++;
}
void dij(int s,int now)
{
memset(vis,false,sizeof(vis));
priority_queue<node>q; q.push({0,s});
dis[now][s]=0;
while (!q.empty())
{
int x=q.top().pos; q.pop();
if(vis[x]) continue; vis[x]=true;
for(int i=head[x];i!=-1;i=ee[i].next)
{
int y=ee[i].to;
if(dis[now][y]>dis[now][x]+ee[i].val){
dis[now][y]=dis[now][x]+ee[i].val;
if(!vis[y]) q.push({dis[now][y],y});
}
}
}
}
ll f[5005],sum;
bool check(ll mid)
{
int Max=0;
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
int g=0;
for(int j=1;j<=k;j++)
{
if(dis[j][i]>mid) continue;
g+=1<<(j-1);
}
f[g]+=a[i]; Max=max(Max,g);
}
Max_Flow flow; flow.s=0,flow.t=Max+k+5;
for(int i=0;i<=Max;i++) flow.add_e(flow.s,i,f[i]);
for(int i=0;i<=Max;i++)
for(int j=0;j<k;j++)
if(i&(1<<j)) flow.add_e(i,Max+j+1,1e16);
for(int i=1;i<=k;i++) flow.add_e(Max+i,flow.t,c[i]);
if(flow.Dinic()==sum) return true;
return false;
}
ll solve()
{
for(int i=1;i<=k;i++) dij(h[i],i);
ll l=0,r=1e16,ans=1e16;
while (r>=l)
{
ll mid=(l+r)/2;
if(check(mid))
ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
void Input()
{
for(int i=0;i<=10;i++)
for(int j=0;j<maxn;j++) dis[i][j]=1e16;
memset(head,-1,sizeof(head));
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),sum+=a[i];
for(int i=1;i<=m;i++){
int u,v; ll w; scanf("%d%d%lld",&u,&v,&w);
add_e(u,v,w);
}
for(int i=1;i<=k;i++) scanf("%lld%lld",&h[i],&c[i]);
}
int main()
{
Input();
printf("%lld\n",solve());
return 0;
}