69 条题解
-
4
PowderHan LV 10 @ 7 年前
-
14 年前@
-
16 年前@
缩点+差分
首先将所有等号边连接的连通块缩点,大于号边反向连(这样就全是小于号了)
然后将缩点后的图进行差分找最长路即可
缩点用并查集,差分用拓扑,这个就不解释了吧 -
16 年前@
为什么都提差分约束啊?
直接缩点,然后按照出度的大小bfs就可以了。 -
19 年前@
P1094关系运算图
Accepted记录信息
评测状态 Accepted
题目 P1094 关系运算图
递交时间 2015-07-10 23:07:45
代码语言 C++
评测机 VijosEx
消耗时间 31 ms
消耗内存 776 KiB
评测时间 2015-07-10 23:07:47评测结果
编译成功
foo.cpp: In function 'void spfa()':
foo.cpp:42:28: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for( i = 0 ; i < link[ now ].size() ; i++ )
^测试数据 #0: Accepted, time = 0 ms, mem = 612 KiB, score = 20
测试数据 #1: Accepted, time = 0 ms, mem = 604 KiB, score = 20
测试数据 #2: Accepted, time = 31 ms, mem = 776 KiB, score = 20
测试数据 #3: Accepted, time = 0 ms, mem = 624 KiB, score = 20
测试数据 #4: Accepted, time = 0 ms, mem = 596 KiB, score = 20
Accepted, time = 31 ms, mem = 776 KiB, score = 100
代码
#include <iostream>
#include <stdio.h>
#include <vector>
#include <queue>
#include <string.h>using namespace std;
int n , m;
vector < int > link[10000 + 2];
vector < int > value[10000 + 2];
int x , y , vt;
int dist[10000 + 2];
bool use[10000 + 2];
int i;
queue < int > q;
bool flag;
int ans;int max( int a , int b )
{
if( a > b )
return a;
return b;
}void spfa()
{
int i , now , cur , w;
q.push( 0 );
dist[0] = 0;
while( !q.empty() )
{
now = q.front();
q.pop();
use[ now ] = 0;
if( dist[now] > n )
{
flag = 1;
break;
}
for( i = 0 ; i < link[ now ].size() ; i++ )
{
cur = link[ now ][i];
w = value[ now ][i];
if( dist[ cur ] < dist[ now ] + w )
{
dist[ cur ] = dist[ now ] + w;
if( !use[ cur ] )
{
use[ cur ] = 1;
q.push( cur );
}
}
}
}
return;
}int main()
{
scanf( "%d %d" , &n , &m );
for( i = 0 ; i < m ; i++ )
{
scanf( "%d %d %d" , &x , &y , &vt );
if( vt == -1 )
{
link[x].push_back( y );
value[x].push_back( 1 );
}
else if( vt == 1 )
{
link[y].push_back( x );
value[y].push_back( 1 );
}
else
{
link[x].push_back( y );
link[y].push_back( x );
value[x].push_back( 0 );
value[y].push_back( 0 );
}
}
for( i = 1 ; i <= n ; i++ )
{
link[0].push_back( i );
value[0].push_back( 0 );
}
memset( dist , -1 , sizeof( dist ) );
spfa();
for( i = 1 ; i <= n ; i++ )
ans = max( ans , dist[i] );
if( flag )
cout << "NO" << endl;
else
cout << ans << endl;
//system( "pause" );
return 0;
}
真~差分约束! -
03 年前@
1
-
07 年前@
-
08 年前@
裸差分约束系统。。。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;/*
输入格式共二行,第一行有二个空格隔开的整数n和m。
n表示G的结点个数,m表示G的边数,其中1<=n<=1000, 0<=m<=10000。
全部结点用1到n标出,图中任何二点之间最多只有一条边,且不存在自环。
第二行共有3m个用空格隔开的整数,第3i-2和第3i-1(1<=i<=m)个数表示第i条边的顶点。
第3i个数表示第i条边上的符号,其值用集合{-1,0,1}中的数表示:-1表示‘<’, 0 表示‘=’, 1表示‘>’。*/
int n,m,d[2000],ans=0x3f3f3f3f;
struct e{int from,to,cost;};
vector<e>G;
void BF(){
int update=true,tot=0;
while(update){
update=false;
tot++;
if(tot>n)break;
for(int i=0;i<G.size();i++){
int from=G[i].from;
int to=G[i].to;
int cost=G[i].cost;
if(d[to]>d[from]+cost)
d[to]=d[from]+cost,update=true;
}
}
if(tot>n)return puts("NO"),void();
for(int i=1;i<=n;i++)ans=min(ans,d[i]);
printf("%d\n",abs(ans));
}int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(z==-1){
//x<y --> x-y<=-1
G.push_back((e){y,x,-1});
}else if(z==0){
//x-y<=0
//y-x<=0
G.push_back((e){x,y,0});
G.push_back((e){y,x,0});
}else{
//x>y --> y-x>=-1
G.push_back((e){x,y,-1});
}
}
BF();
} -
010 年前@
var h,t,i,j,k,m,n,p,ans:longint;
b,c,d,w:array[0..10000] of longint;
x,y,z:longint;
a:array[0..1000,0..1000] of longint;
v:array[0..10000] of boolean;
procedure spfa(x:Longint);
var k:longint;
begin
fillchar(v,sizeof(v),false);
fillchar(d,sizeof(d),0);
fillchar(w,sizeof(w),0);
h:=0;
t:=0;
inc(t);
w[t]:=x;
v[x]:=true;
d[x]:=0;
while (h<>t) do
begin
h:=h mod n +1;
k:=w[h];
inc(c[k]);
if c[k]>2*n then begin writeln('NO'); halt; end;
v[k]:=false;
for i:=1 to n do
if (d[k]+a[k,i]<d[i]) and (a[k,i]<>0) then
begin
d[i]:=d[k]+a[k,i];
if not v[i] then
begin
t:=t mod n +1;
w[t]:=i;
v[i]:=true;
end;
end;
end;
end;
begin
read(m,n);
for i:=1 to m do
begin
read(x,y,z);
if z=1 then begin
a[y,x]:=-1;
// a[y,x]:=1;
end;
if z=-1 then begin
a[x,y]:=-1;
// a[x,y]:=1;
end;
end;
inc(n);
for i:=1 to n-1 do
begin
a[n,i]:=-1;
//a[i,n]:=1;
a[i,i]:=10000000;
end;
spfa(n);
ans:=100000;
for i:=1 to n-1 do
if d[i]<ans then ans:=d[i];
writeln(abs(ans)-1);
end.为什么运行错误~?????
-
010 年前@
#include<cstdio>
const int maxn=2005,maxm=20005;
int m,n;
int map[maxm][3]={0},cost[maxn]={0};
bool updated=true;
int times=0;
int main(){
scanf("%d %d\n",&n,&m);
for(int i=0;i<m;i++){
int x,y,z;
scanf("%d %d %d ",&x,&y,&z);
if(z==1){
map[i][0]=x;
map[i][1]=y;
map[i][2]=z;
}else if(z==0){
map[i][0]=x;
map[i][1]=y;
map[i][2]=z;
i++;m++;
map[i][1]=x;
map[i][0]=y;
map[i][2]=z;
}else{
map[i][0]=y;
map[i][1]=x;
map[i][2]=1;
}
}
while(updated&×<=n){
updated=false;
times++;
for(int i=0;i<m;i++){
int preput=cost[map[i][0]]+map[i][2];
if(cost[map[i][1]]<preput){
cost[map[i][1]]=preput;
updated=true;
}else;
}
}
if(times<=n){
int ans=0;
for(int i=1;i<=n;i++){
if(ans<cost[i])ans=cost[i];
else;
}
printf("%d\n",ans);
}else printf("NO\n");
}
权为0的边必须双向,否则第2,3点过不去。 -
014 年前@
经典啊~~~~~~
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms费了快两个小时了... 终于~~
晒程序:
var
a,e:array [0..1000,0..1000] of longint;
b,d:array [0..1000] of longint;
f:array [1..10000,1..2] of longint;
c:array [1..1000] of boolean;
ans,num,i,j,k,l,n,m,x,y:longint;
stop:boolean;
procedure bll(k,o:longint);
var
j,q,p:longint;
begin
c[k]:=false;
if k=f then begin writeln('NO');stop:=true;exit;end;
if a[k,0]=0 then exit;
for j:=1 to a[k,0] do
if c[a[k,j]] then
begin
bll(a[k,j],o);
if stop then exit;
end;
end;
procedure bl(k:longint);
var
i,j,l,q,p:longint;
begin
c[k]:=false;
for i:=1 to a[k,0] do
if c[a[k,i]] then begin
bl(a[k,i]);
if b[k] -
015 年前@
搞笑 这道题居然有环.用spfa判断环 只要记录每个点的入队列次数 如果次数大于点的总数就有环.
-
015 年前@
也是道蛮经典的题目。
其实很简单。构造一个图。
如果an then begin writeln('NO');halt end;
if v[i]=0 then
begin
inc(ed);
c[ed]:=i;
v[i]:=1
end;
end;
inc(st);
end;
for i:=1 to n do if dis[i]>max then max:=dis[i];
end;begin
init;
spfa;
writeln(max-1);
end. -
015 年前@
var
i,j,x,y,z,n,m,k,max:longint;
count,a,into:array[1..1000] of longint;
b:array[1..1000] of boolean;
g,map:array[1..1000,1..1000] of integer;begin
read(n,m);
fillchar(g,sizeof(g),0);
for i:=1 to m do
begin
read(x,y,z);
if z=-1 then g[x,y]:=1;
if z=1 then g[y,x]:=1;
if z=0 then a[x]:=y;
end;fillchar(b,sizeof(b),true);
for k:=1 to n do
if a[k]0 then for i:=1 to n do
begin
if (g=1)and(ia[k]) then g[i,a[k]]:=1;
if (g[k,i]=1)and(ia[k]) then g[a[k],i]:=1;
b[k]:=false;
end;fillchar(map,sizeof(map),0);
for i:=1 to n do
for j:=1 to n do
if (b[i])and(b[j]) then begin
map:=g;
if map=1 then inc(into[j]);
end;fillchar(count,sizeof(count),0);
for i:=1 to n do
begin
j:=1;
while (j -
015 年前@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms在老师强烈建议用并查集+拓扑排序的情况下我终于用SPFA秒之。
-
015 年前@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms
传说中的bellman_ford -
015 年前@
toplogical sort
-
015 年前@
终于明白这道题目的的AC率为什么会那么低了...
首先要用邻接表
接着bellman_ford
注意,等于的时候要连接一条双向的权为0的边(否则只能60分) -
015 年前@
差分约束
以前用spfa写,不知怎么始终错,今天突发奇想,去学了bellman_ford然后就对了....
倒...看牛人们说的是求最长路,但是我不知怎么写了个最短路...竟然AC?!
看样子RP+++
---|---|---|---|---|---|---|---|---|---|---|-
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 244ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:244ms -
015 年前@
必须从源向所有点连边,我沙茶了!