(7条消息) 食用前须知(阅读并同意后在食用其他部分)_lxrrrrrrrr的博客-CSDN博客
看完进来哈
目录
问题 A: 邻接矩阵存储的图,节点的出度和入度计算(附加代码模式)
问题 B: 算法7-12:有向无环图的拓扑排序
问题 C: 有向图是否存在环?
问题 D: 是否为有效的拓扑序列
问题 E: 案例6-2.6:最短工期
---------------------------------------概念-----------------------------------------
最早发生时间:
最迟发生时间:
关键路径:
--------------------------------------------------------------------------------------
问题 F: 图-节点的最早发生时间
问题 G: 图-节点的最迟发生时间
问题 H: 图-边的最早发生时间
问题 I: 图-边的最迟发生时间
问题 J: 图-图的关键路径
模拟即可
#include
using namespace std;
#define MAX_SIZE 200
struct Graph{
int nodeNumber;
int adjMatrix[MAX_SIZE][MAX_SIZE];
};
void CalculateDegree(const Graph& g,int inDegree[],int outDegree[]){
int n=g.nodeNumber;
for(int i=0;i
拓扑排序板子
从每个入度为0的点开始宽搜即可
#include
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
const int N=1e6+10;
int G[1000][1000];
int n;
int du[1000];
vector ans;
bool tpst() {
int num=0;
stack q;
fer(i,0,n-1){
if(du[i]==0){
q.push(i);
}
}
while(q.size()) {
int u=q.top();
q.pop();
ans.pb(u);
num++;
fer(v,0,n-1){
if(G[u][v]) {
du[v]--;
if(du[v]==0)
q.push(v);
}
}
}
if(num==n){
return true;
}
else{
return false;
}
}
signed main()
{
cin>>n;
fer(i,0,n-1){
fer(j,0,n-1){
cin>>G[i][j];
if(G[i][j]){
du[j]++;
}
}
}
if(tpst()) {
for(auto t:ans){
cout<
判环的话
并查集好写一点
#include
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
const int N=1e6+10;
int p[N];
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
signed main(){
int n,m;
while(cin>>n>>m){
if(!n && !m) break;
fer(i,1,n) p[i]=i;
bool fl=false;
fer(i,1,m){
int a,b;
cin>>a>>b;
if(find(a)!=find(b)){
p[find(a)]=find(b);
}
else{
fl=1;
break;
}
}
if(fl){
cout<<"YES\n";
}
else{
cout<<"NO\n";
}
}
}
计算一下度数即可
#include
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
const int N=1e6+10;
vector v[N];
int inv[N];
int now[N];
int n,m;
int inx[N];
bool check(){
fer(i,0,n) now[i]=inv[i];
for(int i=0;i>inx[i];
}
for(int i=0;i>n>>m;
fer(i,1,m){
int a,b;
cin>>a>>b;
v[a].pb(b);
inv[b]++;
}
int k;
cin>>k;
fer(i,1,k){
if(check()){
cout<<"YES"<
拓扑排序不那么板子的板子题
#include
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
const int N=1e6+10;
int tmp[N];
int h[N],e[N],ne[N],w[N],idx;
int d[N],ans[N];
queue q;
void add(int a,int b,int f){
e[idx]=b,w[idx]=f,ne[idx]=h[a],h[a]=idx++;
}
int n,m;
void solve(){
int ans=0;
while(!q.empty()){
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i]){
d[e[i]]--;
if(d[e[i]]==0) q.push(e[i]);
tmp[e[i]]=max(tmp[e[i]],w[i]+tmp[t]);
ans=max(ans,tmp[e[i]]);
}
}
fer(i,0,n-1){
if(d[i]!=0){
cout<<"Impossible\n";
return;
}
}
cout<>n>>m;
fer(i,1,m){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
d[b]++;
}
fer(i,0,n-1){
if(d[i]==0){
q.push(i);
tmp[i]=0;
}
}
solve();
}
作业上的概念模糊不清,这里稍作解释,是离散数学中的概念
我们以这张图为例
从前往后,前驱结点到当前结点所需时间,取最大值。
如上图中的节点4有两个前驱结点(节点2和3),节点2到节点4的最早发生时间是a1+a3也就是8,节点3到节点4的最早发生时间是a2+a4也就是12,因为12>8,所以节点4的最早发生时间是12.
从后往前,后继结点的最迟发生时间-边权值,取最小值。
也就是求一次最早发生时间,再从出度为0的点反向更新回来求出每个点的最迟时间
最早发生时间和最迟发生时间相同的结点即为关键路径上的节点。
也就是两个都要求一遍呗
而边的最早最迟发生时间大家看作业上的图就知道了,就是看对应的点的最早最迟发生时间
所以我们可以先求点的然后在遍历一遍求出边的最早最迟发生时间
下列代码我没有用拓扑排序写
而是直接宽搜的,然后松弛
拓扑排序本质就是bfs呗
因为后续涉及到对边的操作,所以我用了链式前向星存图
不懂可以csdn一下,很简单的
边bfs边更新每个点的答案
#include
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
const int N=1e6+10;
int h[N],w[N],e[N],ne[N],idx;
void add(int a, int b, int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++ ;
}
int dist[N];
int n,m;
void bfs(){
memset(dist,0,sizeof dist);
dist[1]=0;
queue q;
q.push(1);
while(q.size()){
auto tp=q.front();
q.pop();
for(int i=h[tp];i!=-1;i=ne[i]){
int j=e[i];
if(w[i]+dist[tp]>dist[j]){
dist[j]=dist[tp]+w[i];
q.push(j);
}
}
}
}
signed main(){
memset(h,-1,sizeof h);
cin>>n>>m;
fer(i,1,m){
int a,b,w;
cin>>a>>b>>w;
add(a+1,b+1,w);
}
bfs();
fer(i,1,n){
cout<
我们需要建两张图,一张正向图一张反向图
从第一张图bfs出去求出最早时间,然后在第二张图反向bfs一遍
#include
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
const int N=1e6+10;
int h[N],w[N],e[N],ne[N],idx;
int h2[N],w2[N],e2[N],ne2[N],idx2;
void add1(int a, int b, int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++ ;
}
void add2(int a, int b, int c)
{
e2[idx2]=b,w2[idx2]=c,ne2[idx2]=h2[a],h2[a]=idx2++ ;
}
int dist[N];
int dist2[N];
int n,m;
void bfs(){
memset(dist,0,sizeof dist);
dist[1]=0;
queue q;
q.push(1);
while(q.size()){
auto tp=q.front();
q.pop();
for(int i=h[tp];i!=-1;i=ne[i]){
int j=e[i];
if(w[i]+dist[tp]>dist[j]){
dist[j]=dist[tp]+w[i];
q.push(j);
}
}
}
memset(dist2,0x3f,sizeof dist2);
queue q2;
fer(i,1,n){
if(h[i]==-1){
dist2[i]=dist[i];
q2.push(i);
}
}
while(q2.size()){
auto tp=q2.front();
q2.pop();
for(int i=h2[tp];i!=-1;i=ne2[i]){
int j=e2[i];
if(dist2[tp]-w2[i]>n>>m;
fer(i,1,m){
int a,b,w;
cin>>a>>b>>w;
add1(a+1,b+1,w);
add2(b+1,a+1,w);
}
bfs();
fer(i,1,n){
cout<
和点的最早发生时间一样
这条边是那个点引出来的答案就和这个点的最早发生时间一样
#include
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
const int N=1e6+10;
int h[N],w[N],e[N],ne[N],idx;
int res[N];
void add(int a, int b, int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++ ;
}
int dist[N];
int n,m;
void bfs(){
memset(dist,0,sizeof dist);
dist[1]=0;
queue q;
q.push(1);
while(q.size()){
auto tp=q.front();
q.pop();
for(int i=h[tp];i!=-1;i=ne[i]){
int j=e[i];
if(w[i]+dist[tp]>dist[j]){
dist[j]=dist[tp]+w[i];
q.push(j);
}
}
}
}
signed main(){
memset(h,-1,sizeof h);
cin>>n>>m;
fer(i,1,m){
int a,b,w;
cin>>a>>b>>w;
add(a+1,b+1,w);
}
bfs();
fer(node,1,n){
for(int i=h[node];i!=-1;i=ne[i]){
res[i]=dist[node];
}
}
fer(i,0,m-1){
cout<
和点的最迟发生时间一样
这条边指向那个点的答案就是这个点的最迟发生时间减去权值
#include
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
const int N=1e6+10;
int h[N],w[N],e[N],ne[N],idx;
int h2[N],w2[N],e2[N],ne2[N],idx2;
void add1(int a, int b, int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++ ;
}
void add2(int a, int b, int c)
{
e2[idx2]=b,w2[idx2]=c,ne2[idx2]=h2[a],h2[a]=idx2++ ;
}
int dist[N];
int dist2[N];
int n,m;
void bfs(){
memset(dist,0,sizeof dist);
dist[1]=0;
queue q;
q.push(1);
while(q.size()){
auto tp=q.front();
q.pop();
for(int i=h[tp];i!=-1;i=ne[i]){
int j=e[i];
if(w[i]+dist[tp]>dist[j]){
dist[j]=dist[tp]+w[i];
q.push(j);
}
}
}
memset(dist2,0x3f,sizeof dist2);
queue q2;
fer(i,1,n){
if(h[i]==-1){
dist2[i]=dist[i];
q2.push(i);
}
}
while(q2.size()){
auto tp=q2.front();
q2.pop();
for(int i=h2[tp];i!=-1;i=ne2[i]){
int j=e2[i];
if(dist2[tp]-w2[i]>n>>m;
fer(i,1,m){
int a,b,w;
cin>>a>>b>>w;
add1(a+1,b+1,w);
add2(b+1,a+1,w);
}
bfs();
fer(node,1,n){
for(int i=h[node];i!=-1;i=ne[i]){
int j=e[i];
res[i]=dist2[j]-w[i];
}
}
fer(i,0,m-1){
cout<
两个都求一边
然后看相等
#include
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
const int N=1e6+10;
int h[N],w[N],e[N],ne[N],idx;
int h2[N],w2[N],e2[N],ne2[N],idx2;
void add1(int a, int b, int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++ ;
}
void add2(int a, int b, int c)
{
e2[idx2]=b,w2[idx2]=c,ne2[idx2]=h2[a],h2[a]=idx2++ ;
}
int dist[N];
int dist2[N];
int n,m;
void bfs(){
memset(dist,0,sizeof dist);
dist[1]=0;
queue q;
q.push(1);
while(q.size()){
auto tp=q.front();
q.pop();
for(int i=h[tp];i!=-1;i=ne[i]){
int j=e[i];
if(w[i]+dist[tp]>dist[j]){
dist[j]=dist[tp]+w[i];
q.push(j);
}
}
}
memset(dist2,0x3f,sizeof dist2);
queue q2;
fer(i,1,n){
if(h[i]==-1){
dist2[i]=dist[i];
q2.push(i);
}
}
while(q2.size()){
auto tp=q2.front();
q2.pop();
for(int i=h2[tp];i!=-1;i=ne2[i]){
int j=e2[i];
if(dist2[tp]-w2[i] edge;
signed main(){
memset(h,-1,sizeof h);
memset(h2,-1,sizeof h2);
cin>>n>>m;
fer(i,1,m){
int a,b,w;
cin>>a>>b>>w;
edge.push_back({a,b});
add1(a+1,b+1,w);
add2(b+1,a+1,w);
}
bfs();
fer(node,1,n){
for(int i=h[node];i!=-1;i=ne[i]){
res[i]=dist[node];
}
}
fer(node,1,n){
for(int i=h[node];i!=-1;i=ne[i]){
int j=e[i];
res2[i]=dist2[j]-w[i];
}
}
fer(i,0,m-1){
if(res[i]==res2[i]){
cout<"<