2527: THE END IS COMING!!!
瞎了眼没看清样例,我怕不是个傻叉。。。。
转自题解,然后自己码了码代码
思路还是挺巧妙的,首先我们需要知道这k个名额只能用于不能到达的,日狗这点真的坑
第二,我们还要知道元素可以拆分,分成每一个元素分开计算
第三,我们还要知道怎么建图
我们只有 5 种元素,所以可以全部分开考虑
每种元素单独考虑
每个点拆成两部分,一个用于接受元素,一个用于往外送元素。
源点向每个点的接受元素部分建立流量为当前节点需要元素数量,费用为 1 的边。
向用于外送元素的部分建立流量为当前节点需要元素数量,费用为 0 的边。
外送元素部分向所有能及时赶到的部分建立流量为正无穷,费用为 0 的边,意味着同一个元
素又去了其他地方。
每个接受元素的部分向超级汇点建立流量为当前节点需要元素数量,费用为 0 的边,意味着
这个点接收到了足够多的元素。
每个离起点距离不支持的点记录数量,超过 k 就是无解。
处理过程中跳过这些点就好了
总结一下就是
对于每一个点从源点到这个点建立容量为需求,费用为1的边,从这个点到终点建立容量为需求,费用为0的边
对于可能发生的转移,我们需要一个虚拟节点,代表的是i这个节点能向其它转移的元素的个数,所以从源点开始向虚拟节点连接容量为需求,费用为0的点,同时向所有能转移的点连接容量为需求,费用为0的节点
这样子为什么是正确的呢?
我想了想,对于每一个节点,可以从源点直接拿元素,也可以由其他转移过来,但是最大流是固定的,就是所有的需求,所以即使求最小费用的过程,当你不能从其它节点得到流量,只能通过自己从源点拿元素,费用为1,以保证最大流
#include <bits/stdc++.h>
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define Pb push_back
#define FI first
#define SE second
#define For(i,a,b) for(int i = a; i < b; ++i)
#define IOS ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int prime = 999983;
const int INF = 1e8;
const LL INFF =0x7FFFFFFFFFFFFFFF;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-6;
const LL mod = 1e9 + 7;
LL qpow(LL a,LL b){LL s=1;while(b>0){if(b&1)s=s*a%mod;a=a*a%mod;b>>=1;}return s;}
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
int dr[2][4] = {1,-1,0,0,0,0,-1,1};
typedef pair<int,int> P;
struct Edge{
int from,to,cap,flow,cost;
};
const int maxn = 5000+100;
struct MCMF{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
int inq[maxn];
int d[maxn];
int p[maxn];
int a[maxn];
void init(int n){
this->n = n;
for(int i = 0;i < n; ++i) G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int cap,int cost){
edges.push_back((Edge){from,to,cap,0,cost});
edges.push_back((Edge){to,from,0,0,-cost});
int m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BellmanFord(int s,int t,int &flow,int &cost){
for(int i = 0;i < n; ++i) d[i] = INF;
memset(inq,0,sizeof(inq));
d[s] = 0,inq[s] = 1;p[s] = 0,a[s] = INF;
queue<int> Q;
Q.push(s);
while(!Q.empty()){
int u = Q.front(); Q.pop();
inq[u] = 0;
for(int i = 0;i < G[u].size(); ++i){
Edge& e = edges[G[u][i]];
if(e.cap > e.flow &&d[e.to] > d[u]+e.cost){
d[e.to] = d[u]+e.cost;
p[e.to] = G[u][i];
a[e.to] = min(a[u],e.cap-e.flow);
if(!inq[e.to]) {
Q.push(e.to); inq[e.to] = 1;
}
}
}
}
if(d[t] == INF) return false;
flow += a[t];
cost += d[t]*a[t];
int u = t;
while(u != s){
edges[p[u]].flow += a[t];
edges[p[u]^1].flow -= a[t];
u = edges[p[u]].from;
}
return true;
}
int Mincost(int s,int t,int &flow,int &cost){
flow = 0,cost = 0;
while(BellmanFord(s,t,flow,cost));
return cost;
}
};
MCMF mcmf;
// const int maxn = 100+10;
int x[maxn],y[maxn],st[maxn],ut[maxn],c[maxn][6];
int sx,sy;
bool keda[maxn];
int main(void)
{
int n,m,k;
cin>>n>>m>>k;
cin>>sx>>sy;
int cnt = 0;
for(int i = 1;i < n; ++i){
cin>>x[i]>>y[i]>>st[i]>>ut[i];
for(int j = 1;j <= m; ++j)
cin>>c[i][j];
int dis =abs(x[i]-sx)+abs(y[i]-sy);
if(dis > st[i])
cnt++;
else
keda[i] = true;
}
if(cnt > k)
return 0*puts("THE END IS COMING!!!!!");
// cout<<cnt<<endl;
int ans = 0;
for(int j = 1;j <= m; ++j){
mcmf.init(2*n+1);
for(int i = 1;i < n; ++i){
if(!keda[i]) continue;
mcmf.AddEdge(0,i,c[i][j],1);
mcmf.AddEdge(i,n+i,c[i][j],0);
mcmf.AddEdge(0,n+i,c[i][j],0);
for(int k = 1;k < n; ++k){
int dis =abs(x[i]-x[k])+abs(y[i]-y[k]);
if(keda[k]&&k != i&&st[i]+ut[i]+dis <= st[k])
{
mcmf.AddEdge(n+i,k,c[i][j],0);
// cout<<i<<" "<<k<<endl;
}
}
mcmf.AddEdge(i,2*n,c[i][j],0);
}
int flow,cost;
ans += mcmf.Mincost(0,2*n,flow,cost);
// ans += cost;
}
cout<<ans<<endl;
// int n,m,s,t;
// scanf("%d %d %d %d",&n,&m,&s,&t);
// int u,v,w,c;
// mcmf.init(n+1);
// while(m--){
// scanf("%d %d %d %d",&u,&v,&w,&c);
// mcmf.AddEdge(u,v,w,c);
// }
// int flow,cost;
// flow = 0,cost = 0;
// mcmf.Mincost(s,t,flow,cost);
// printf("%d %d\n",flow,cost);
return 0;
}