题意:给定一个无向图,从起点到终点,只有走最短路!!!(这句话非常重要)才能在规定时限内到达,问最少去掉几条边使不能到达,最多去掉几条边仍能到达。
思路:由于是走最短路才能到达,首先的预处理就是求最短路!求出来最短路之后,把所有最短路的边添加到图里面,然后再在这个新建的图上进行操作,最少去掉几条边就是求边权值都相等的最大流,最多去掉几条边就是求边权值都相等的最短路!!这题的主要考点就是在最短路上面!!预处理非常重要。。。这题由于没搞清楚要走最短路wa哇傻了。。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int oo=1e9;
/**oo 表示无穷大*/
const int mm=111111111;
/**mm 表示边的最大数量,记住要是原图的两倍,在加边的时候都是双向的*/
const int mn=2010;
/**mn 表示点的最大数量*/
int node,src,dest,edge;
/**node 表示节点数,src 表示源点,dest 表示汇点,edge 统计边数*/
int ver[mm],flow[mm],nex[mm];
/**ver 边指向的节点,flow 边的容量 ,next 链表的下一条边*/
int head[mn],work[mn],dis[mn],q[mn];
void prepare(int _node, int _src,int _dest)
{
node=_node,src=_src,dest=_dest;
for(int i=0; i=0; i=nex[i])
if(flow[i]&&dis[v=ver[i]]<0)
{
/**这条边必须有剩余容量*/
dis[q[r++]=v]=dis[u]+1;
if(v==dest) return 1;
}
return 0;
}
/**寻找可行流的增广路算法,按节点的距离来找,加快速度*/
int Dinic_dfs( int u, int exp)
{
if(u==dest) return exp;
/**work 是临时链表头,这里用 i 引用它,这样寻找过的边不再寻找*/
for( int &i=work[u],v,tmp; i>=0; i=nex[i])
if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
{
flow[i]-=tmp;
flow[i^1]+=tmp;
/**正反向边容量改变*/
return tmp;
}
return 0;
}
int Dinic_flow()
{
int i,ret=0,delta;
while(Dinic_bfs())
{
for(i=0; iq;
for (int i=0; i<=n; i++)
di[i]=oo;
memset(vis,0,sizeof(vis));
q.push(s);
di[s]=0;
while(!q.empty())
{
int h=q.front();
q.pop();
vis[h]=0;
for (int i=hea[h]; i!=-1; i=x[i].next)
{
int v=x[i].to;
int w=x[i].w;
if (di[v]>di[h]+w)
{
di[v]=di[h]+w;
if (!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}
int ip=0;
void add(int u,int v,int w)
{
x[ip].to=v,x[ip].w=w,x[ip].next=hea[u],hea[u]=ip++;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
ip=0;
memset(hea,-1,sizeof(hea));
for(int i=0; i