暂无链接
图
【题目描述】
Shy 有一张 n 个点 m 条边的无向带权图。
求图中包含点数最少的正环包含多少个点。
【输入】
第一行两个整数 n,m 表示点数和边数。
接下来 m 行每行三个整数 x,y,z,p 表示 x 到 y 存在一条边权为 z 的边,y 到 x 存在一条边权为 p 的边。
数据保证无重边和自环。
【输出】
输出一个数表示包含点数最少的正环包含多少个点。如果不存在正环,输出 0。
【输入样例】
4 4
1 2 -10 3
1 3 1 -10
2 4 -10 -1
3 4 0 -3
【输出样例】
4
【提示】
【数据规模】
对于 30%的数据,1≤n≤100;
对于 60%的数据,1≤n≤150;
对于 100%的数据,1≤n≤300,0≤m≤n*(n-1)/2,1≤x,y≤n, -10000≤z≤10000。
题解
据说正解是倍增+ Floyed F l o y e d ???
然而。。。
这是考验我 dfs d f s 的剪枝技术吗???
二分包含的点数, dfs d f s 找最长路(正环),当当前点的最长路小于0时直接减掉即可 AC A C
这场的出题人是真的毒瘤。。。mmp
代码
#include<bits/stdc++.h>
using namespace std;
const int M=305;
struct sd{int n,d;};
int dis[M],n,m;
bool vis[M];
vector<sd>mmp[M];
void in()
{
int a,b,c,d;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
if(c+d>0)printf("2\n"),exit(0);
mmp[a].push_back((sd){b,c});
mmp[b].push_back((sd){a,d});
}
}
bool dfs(int v,int cot,int bd)
{
if(cot>bd||dis[v]<0)return 0;
vis[v]=1;int t,d;
for(int i=mmp[v].size()-1;i>=0;--i)
{
t=mmp[v][i].n;d=mmp[v][i].d;
if(dis[t]<=dis[v]+d)
{
dis[t]=dis[v]+d;
if(!vis[t])
{if(dfs(t,cot+1,bd))return 1;}
else return 1;
}
}
vis[v]=0;
return 0;
}
void reset(int s){memset(vis,0,sizeof(vis));fill(dis+1,dis+1+n,-INT_MAX/3);dis[s]=0;}
bool check(int bd){for(int i=1;i<=n;++i){reset(i);if(dfs(i,1,bd))return 1;}return 0;}
void ac()
{
int le=3,ri=n,mid,ans;
while(le<=ri)
{
mid=(le+ri)>>1;
if(check(mid))ans=mid,ri=mid-1;
else le=mid+1;
}
printf("%d",ans);
}
int main()
{
in();ac();
return 0;
}