নির্দেশিত গ্রাফে সমস্ত চক্র সন্ধান করা


198

প্রদত্ত নোড থেকে / নির্দেশিত গ্রাফের সমস্ত চক্রটি কীভাবে (পুনরাবৃত্তি হবে) খুঁজে পেতে পারি?

উদাহরণস্বরূপ, আমি এই জাতীয় কিছু চাই:

A->B->A
A->B->C->A

তবে তা নয়: বি-> সি-> বি


1
হোমওয়ার্ক আমি ধরে নিই? me.utexas.edu/~bard/IP/Handouts/cycles.pdf এটা বৈধ প্রশ্ন নয় :) :)
শুগকিউক

5
মনে রাখবেন এটি কমপক্ষে এনপি হার্ড। সম্ভবত PSPACE, আমাকে এটি সম্পর্কে ভাবতে হবে, তবে জটিলতার তত্ত্বের জন্য খুব সকালে খুব তাড়াতাড়ি বি-)
ব্রায়ান পোস্তো

2
(- বনাম +1 টি ঙ) -1 বিভিন্ন চক্র (যদিও সব আপনার ইনপুট গ্রাফ বনাম ছেদচিহ্ন এবং ই প্রান্ত থাকে তাহলে 2 ^ হয় পারে সহজ চক্র হতে)। এটি যথেষ্ট পরিমাণে - আপনি সম্ভবত এগুলি সমস্ত লিখতে চাইবেন না। এছাড়াও, আউটপুট আকারটি তাত্পর্যপূর্ণ হওয়ায় অ্যালগরিদমের জটিলতা বহুপদী হতে পারে না। আমি মনে করি এখনও এই প্রশ্নের উত্তর নেই।
CygnusX1

1
আমার জন্য আমার সেরা বিকল্পটি ছিল: ব্যক্তিগত.কেন্ট.ইডু
আরমুহাম্মা

উত্তর:


105

আমি এই পৃষ্ঠাটি আমার সন্ধানে পেয়েছি এবং যেহেতু চক্রগুলি দৃ strongly়ভাবে সংযুক্ত উপাদানগুলির মতো নয়, তাই আমি অনুসন্ধান চালিয়ে যাচ্ছি এবং শেষ পর্যন্ত, আমি একটি কার্যকর অ্যালগরিদম পেয়েছি যা নির্দেশিত গ্রাফের সমস্ত (প্রাথমিক) চক্রকে তালিকাভুক্ত করে। এটি ডোনাল্ড বি জনসনের এবং পেপারটি নিম্নলিখিত লিঙ্কটিতে পাওয়া যাবে:

http://www.cs.tufts.edu/comp/150GA/homeworks/hw1/Johnson%2075.PDF

একটি জাভা বাস্তবায়ন পাওয়া যাবে:

http://normalisiert.de/code/java/elementaryCycles.zip

জনসনের অ্যালগরিদমের একটি গণিতের প্রদর্শন এখানে পাওয়া যাবে , বাস্তবায়ন ডান থেকে ডাউনলোড করা যেতে পারে ( "লেখকের কোড ডাউনলোড করুন" )।

দ্রষ্টব্য: আসলে এই সমস্যার জন্য অনেকগুলি অ্যালগরিদম রয়েছে। তাদের কিছু এই নিবন্ধে তালিকাভুক্ত করা হয়েছে:

http://dx.doi.org/10.1137/0205007

নিবন্ধ অনুসারে, জনসনের অ্যালগরিদম দ্রুততম।


1
আমি কাগজটি থেকে বাস্তবায়নের জন্য এ জাতীয় ঝামেলা পেয়েছি এবং শেষ পর্যন্ত এই অগ্রিরিথমে এখনও টার্জন প্রয়োগের প্রয়োজন। এবং জাভা-কোডও ঘৃণ্য। :(
গ্লেনো

7
@ গ্লেনো ওয়েল, আপনি যদি বোঝাতে চান যে আপনি টার্জনকে বাকী প্রয়োগের পরিবর্তে গ্রাফের সমস্ত চক্র সন্ধান করতে পারেন তবে আপনি ভুল। এখানে , আপনি দৃ strongly়ভাবে সংযুক্ত উপাদান এবং সমস্ত চক্রের মধ্যে পার্থক্য দেখতে পাচ্ছেন (চক্র সিডি এবং জিও টার্জনের আলগ দিয়ে ফিরে আসবে না) (@ ব্যাটব্র্যাট আপনার বিভ্রান্তির উত্তরটি এখানেও লুকিয়ে রয়েছে: টার্জনের দ্বারা সমস্ত সম্ভাব্য চক্র ফেরত আসেনি) আলগা, সুতরাং এর জটিলতা তাত্পর্যপূর্ণ চেয়ে ছোট হতে পারে)। জাভা-কোডটি আরও ভাল হতে পারে, তবে এটি কাগজ থেকে বাস্তবায়নের প্রচেষ্টাটিকে বাঁচিয়েছে।
eminsenay

4
এই উত্তরটি নির্বাচিত উত্তরের চেয়ে অনেক ভাল। আমি দৃ a়ভাবে সংযুক্ত উপাদানগুলি থেকে কীভাবে সমস্ত সহজ চক্র পেতে পারি তা নির্ধারণের চেষ্টা করার জন্য বেশ কিছুক্ষণ সংগ্রাম করেছি। দেখা যাচ্ছে এটি অপ্রয়োজনীয় is জনসনের কাগজটিতে একটি দুর্দান্ত অ্যালগরিদম রয়েছে তবে এটি চালানো একটু কঠিন is আমি জাভা বাস্তবায়নের দিকে তাকালাম এবং মতলবতে আমার নিজস্ব রোল করি। কোডটি gist.github.com/1260153উপলব্ধ
কোডিপ্পো

5
@মোটুয়েশ: সম্ভবত আমি কিছু মিস করছি, তবে জনসন পেপার (এবং অন্যান্য উত্স) অনুসারে, একটি চক্র প্রাথমিক হয় যদি কোনও ভার্টেক্স (শুরু / সমাপ্তি বাদে) একাধিকবার প্রদর্শিত না হয়। সেই সংজ্ঞা অনুসারে, A->B->C->Aপ্রাথমিকও নয়?
স্মারকগুলি

9
এটির জন্য অজগর ব্যবহারকারী যে কোনও ব্যক্তির জন্য দ্রষ্টব্য: জনসন অ্যালগরিদম simple_cycleনেটওয়ার্কেক্স হিসাবে প্রয়োগ করা হয়েছে।
জোয়েল

35

ব্যাকট্র্যাকিংয়ের সাথে গভীরতার প্রথম অনুসন্ধান এখানে কাজ করা উচিত। আপনি কোনও নোড আগে গেছেন কিনা তা ট্র্যাক রাখতে বুলিয়ান মানগুলির একটি অ্যারে রাখুন। আপনি যদি যেতে নতুন নোডের বাইরে চলে যান (কোনও নোড না ফেলে আপনি ইতিমধ্যে গেছেন) তবে কেবল ব্যাকট্র্যাক করুন এবং একটি ভিন্ন শাখা চেষ্টা করুন try

আপনার যদি গ্রাফ উপস্থাপনের জন্য সংলগ্ন তালিকা থাকে তবে ডিএফএস কার্যকর করা সহজ। উদাহরণস্বরূপ [অ্যা] = {বি, সি} নির্দেশ করে যে বি এবং সি এ এর ​​সন্তান are

উদাহরণস্বরূপ, নীচে সিউডো-কোড। "শুরু" হ'ল নোড যা থেকে আপনি শুরু করেন।

dfs(adj,node,visited):  
  if (visited[node]):  
    if (node == start):  
      "found a path"  
    return;  
  visited[node]=YES;  
  for child in adj[node]:  
    dfs(adj,child,visited)
  visited[node]=NO;

স্টার্ট নোড দিয়ে উপরের ফাংশনটি কল করুন:

visited = {}
dfs(adj,start,visited)

2
ধন্যবাদ। আমি এখানে বর্ণিত অন্যদের মধ্যে এই পদ্ধতির পছন্দ করি কারণ এটি সহজ (র) বোঝা সহজ এবং যুক্তিসঙ্গত সময় জটিলতা রয়েছে, যদিও এটি সম্ভবত অনুকূল নয়।
redcalx

1
এটি কীভাবে সমস্ত চক্রটি আবিষ্কার করে?
মস্তিষ্কের ঝড়

3
if (node == start): - node and startপ্রথম কলটিতে কী আছে
মস্তিষ্কের ঝড়

2
@ user1988876 এটি প্রদত্ত শীর্ষবিন্দু (যা হবে start) জড়িত সমস্ত চক্র খুঁজে বের করবে । এটি সেই শীর্ষবিন্দু থেকে শুরু হয় এবং ডিএফএস করে যতক্ষণ না এটি আবার সেই শীর্ষবিন্দুতে ফিরে আসে, তারপরে এটি জানে যে এটি একটি চক্র খুঁজে পেয়েছে। তবে এটি আসলে চক্রগুলি আউটপুট দেয় না, কেবল তাদের মধ্যে একটি গণনা (তবে এটি করার জন্য এটি পরিবর্তন করা খুব কঠিন হওয়া উচিত নয়)।
বার্নহার্ড বার্কার

1
@ ব্যবহারকারী ১৯৮৮৮76 Well ঠিক আছে, এটি সন্ধানের চক্রের সংখ্যার সমান পরিমাণের "একটি পথ খুঁজে পেয়েছিল" কেবল এটি মুদ্রণ করে (এটি সহজেই একটি গণনা দ্বারা প্রতিস্থাপন করা যেতে পারে)। হ্যাঁ, এটি কেবল চক্রটি সনাক্ত করবে start। আপনাকে সত্যিকার অর্থে পরিদর্শন করা ফ্ল্যাগগুলি সাফ করার দরকার নেই কারণ প্রতিটি ভিজিট করা পতাকা কারণে সাফ হবে visited[node]=NO;। তবে মনে রাখবেন যে আপনার যদি একটি চক্র থাকে তবে আপনি A->B->C->Aএটি 3 বার সনাক্ত startকরতে পারবেন, এর মধ্যে যে কোনও 3 হতে পারে। এটি রোধ করার জন্য একটি ধারণা হ'ল আরেকটি পরিদর্শন করা অ্যারে যেখানে প্রতিটি নোড যা startকোনও কোনও মুহুর্তে নোড সেট করা থাকে এবং তারপরে আপনি এগুলি পুনর্বিবেচনা করবেন না।
বার্নহার্ড বার্কার

23

প্রথমত - আপনি আক্ষরিকভাবে সমস্ত চক্রটি সন্ধান করতে চান না কারণ যদি সেখানে 1 হয় তবে সেইগুলির একটি অসীম সংখ্যা রয়েছে। উদাহরণস্বরূপ এবিএ, আব্বা ইত্যাদি বা 2 টি চক্রকে 8-জাতীয় চক্র ইত্যাদিতে একসাথে যুক্ত করা সম্ভব হতে পারে ইত্যাদি ইত্যাদি ... অর্থবোধক পদ্ধতির মধ্যে রয়েছে সমস্ত তথাকথিত সহজ চক্রগুলি অনুসন্ধান করা - যাঁরা নিজেকে অতিক্রম করে না তারা ব্যতীত শুরু / শেষ পয়েন্টে তারপরে আপনি যদি চান তবে আপনি সাধারণ চক্রের সংমিশ্রণ তৈরি করতে পারেন।

নির্দেশিত গ্রাফের সমস্ত সহজ চক্র সন্ধানের জন্য বেসলাইন অ্যালগরিদমগুলির মধ্যে একটি হ'ল: গ্রাফের সমস্ত সহজ পাথ (যারা নিজেরাই অতিক্রম করে না) একটি গভীরতার প্রথম ট্রভারসালাল করুন। প্রত্যেকবার যখন বর্তমান নোডের স্ট্যাকের উত্তরসূরি রয়েছে তখন একটি সাধারণ চক্র আবিষ্কার করা হয়। এটি স্ট্যাকের উপাদানগুলিকে চিহ্নিত উত্তরসূরির সাথে শুরু করে এবং স্ট্যাকের শীর্ষে সমাপ্ত হয়। সমস্ত সাধারণ পাথের গভীরতা প্রথম ট্র্যাভারসাল গভীরতা প্রথম অনুসন্ধানের সমান তবে আপনি স্ট্যাক পয়েন্ট হিসাবে বর্তমানে স্ট্যাকের বাইরে অন্য কোনও ভিজিট নোডগুলি চিহ্নিত / রেকর্ড করেন না।

উপরের ব্রুট ফোর্স অ্যালগরিদম মারাত্মকভাবে অদক্ষ এবং এটি ছাড়াও চক্রের একাধিক অনুলিপি তৈরি করা হয়। এটি তবে একাধিক ব্যবহারিক অ্যালগরিদমের শুরুতে যা কর্মক্ষমতা উন্নত করতে এবং চক্রের সদৃশতা এড়াতে বিভিন্ন বর্ধিতকরণ প্রয়োগ করে। আমি কিছু সময় আগে অবাক হয়ে জানতে পারি যে এই অ্যালগরিদমগুলি পাঠ্যপুস্তক এবং ওয়েবে সহজেই পাওয়া যায় না। সুতরাং আমি এখানে কিছু মুক্ত গবেষণা করেছি এবং একটি মুক্ত উত্স জাভা লাইব্রেরিতে অনির্দেশিত গ্রাফগুলিতে চক্রের জন্য এই জাতীয় 4 টি অ্যালগরিদম এবং 1 অ্যালগরিদম বাস্তবায়ন করেছি: http://code.google.com/p/niographs/

বিটিডাব্লু, যেহেতু আমি অপ্রচলিত গ্রাফ উল্লেখ করেছি: সেগুলির জন্য অ্যালগরিদম আলাদা। একটি বিস্তৃত গাছ তৈরি করুন এবং তারপরে গাছের অংশ নয় এমন প্রতিটি প্রান্ত গাছের কয়েকটি প্রান্তের সাথে একসাথে একটি সাধারণ চক্র গঠন করে। এই পথে পাওয়া চক্রগুলি তথাকথিত চক্র বেস তৈরি করে। 2 বা ততোধিক স্বতন্ত্র বেস চক্রকে একত্রিত করে সমস্ত সাধারণ চক্রগুলি পাওয়া যায়। আরও তথ্যের জন্য দেখুন: উদাহরণস্বরূপ: http://dspace.mit.edu/bitstream/handle/1721.1/68106/FTL_R_1982_07.pdf


উদাহরণস্বরূপ কিভাবে ব্যবহার করতে jgraphtহয় যা ব্যবহার করা হয় http://code.google.com/p/niographs/আপনার কাছ থেকে উদাহরণ নিতে পারেন github.com/jgrapht/jgrapht/wiki/DirectedGraphDemo
Vishrant

19

এই সমস্যাটি সমাধান করার জন্য আমি যে সহজ পছন্দটি পেয়েছি তা হ'ল পাইথন লাইব নামে পরিচিত networkx

এটি এই প্রশ্নের উত্তরের উত্তরে উল্লিখিত জনসনের অ্যালগরিদম প্রয়োগ করে তবে তা কার্যকর করা সহজ করে তোলে।

সংক্ষেপে আপনার নিম্নলিখিত প্রয়োজন:

import networkx as nx
import matplotlib.pyplot as plt

# Create Directed Graph
G=nx.DiGraph()

# Add a list of nodes:
G.add_nodes_from(["a","b","c","d","e"])

# Add a list of edges:
G.add_edges_from([("a","b"),("b","c"), ("c","a"), ("b","d"), ("d","e"), ("e","a")])

#Return a list of cycles described as a list o nodes
list(nx.simple_cycles(G))

উত্তর: [['এ', 'বি', 'ডি', 'ই'], ['এ', 'বি', 'সি']]

এখানে চিত্র বর্ণনা লিখুন


1
আপনি একটি নেটওয়ার্কেক্স গ্রাফে একটি অভিধানও আবিষ্কার করতে পারেন:nx.DiGraph({'a': ['b'], 'b': ['c','d'], 'c': ['a'], 'd': ['e'], 'e':['a']})
লুক মাইলস

আমি একটি প্রারম্ভিক শীর্ষটি কীভাবে নির্দিষ্ট করব?
নাক ডাকা

5

স্পষ্ট করা:

  1. দৃ Conn়ভাবে সংযুক্ত উপাদানগুলি সমস্ত উপগ্রহগুলি খুঁজে পেতে পারে যার মধ্যে কমপক্ষে একটি চক্র রয়েছে, গ্রাফের সমস্ত সম্ভাব্য চক্র নয়। উদাহরণস্বরূপ, যদি আপনি সমস্ত দৃ connected়ভাবে সংযুক্ত উপাদানগুলি গ্রহণ করেন এবং ভাঙ্গা / গোষ্ঠী / সেগুলির প্রত্যেককে একটি নোডে (যেমন উপাদান অনুসারে নোড) একীভূত করেন, আপনি কোনও চক্রবিহীন একটি গাছ পাবেন (একটি ডিএজি আসলে)। প্রতিটি উপাদান (যা মূলত এটিতে কমপক্ষে একটি চক্র সহ একটি সাবগ্রাফ্ট) অভ্যন্তরীণভাবে আরও অনেকগুলি সম্ভাব্য চক্র ধারণ করতে পারে, সুতরাং এসসিসি সমস্ত সম্ভাব্য চক্রটি খুঁজে পাবে না, এটি কমপক্ষে একটি চক্রযুক্ত সমস্ত সম্ভাব্য গোষ্ঠী খুঁজে পাবে এবং আপনি যদি গ্রুপ করেন তবে তাদের, তারপরে গ্রাফের চক্র থাকবে না।

  2. গ্রাফের সমস্ত সাধারণ চক্র খুঁজে পেতে , যেমন অন্যরা উল্লেখ করেছেন, জনসনের অ্যালগরিদম একজন প্রার্থী।


3

আমাকে একবার সাক্ষাত্কারের প্রশ্ন হিসাবে এটি দেওয়া হয়েছিল, আমার সন্দেহ হয় এটি আপনার সাথে ঘটেছে এবং আপনি এখানে সাহায্যের জন্য আসছেন। সমস্যাটি তিনটি প্রশ্নের মধ্যে ভাঙ্গা এবং এটি আরও সহজ হয়ে যায়।

  1. আপনি পরবর্তী বৈধ রুটটি কীভাবে নির্ধারণ করবেন
  2. পয়েন্ট ব্যবহার করা হয়েছে কিনা তা আপনি কীভাবে নির্ধারণ করবেন
  3. আপনি কীভাবে আবার একই পয়েন্টটি অতিক্রম করতে পারবেন না

সমস্যা 1) পুনরাবৃত্ত রুটের ফলাফলগুলির একটি উপায় সরবরাহ করতে পুনরাবৃত্তকারী প্যাটার্নটি ব্যবহার করুন। পরের রুটটি পাওয়ার জন্য যুক্তি যুক্ত করার জন্য একটি ভাল জায়গা সম্ভবত আপনার পুনরুক্তিকারীর "মুভনেক্সট"। একটি বৈধ রুট খুঁজতে, এটি আপনার ডেটা কাঠামোর উপর নির্ভর করে। আমার জন্য এটি বৈধ রুটের সম্ভাবনায় পূর্ণ একটি বর্গাকার টেবিল ছিল তাই আমাকে একটি উত্স প্রদত্ত বৈধ গন্তব্যগুলি পেতে একটি কোয়েরি তৈরি করতে হয়েছিল।

সমস্যা 2) প্রতিটি নোডকে ধাক্কা দেওয়ার সাথে সাথে আপনি যখন সেগুলি সংগ্রহ করতে পেলেন, এটির অর্থ হ'ল আপনি উড়ন্ত স্থানে যে সংগ্রহটি তৈরি করছেন তা জিজ্ঞাসাবাদ করে আপনি খুব সহজেই কোনও বিন্দুতে "দ্বিগুণ ফিরে" যাচ্ছেন কিনা তা দেখতে পাবেন।

সমস্যা 3) যদি কোনও মুহুর্তে আপনি দেখতে পান যে আপনি পিছিয়ে দ্বিগুণ হয়ে যাচ্ছেন, আপনি সংগ্রহ থেকে জিনিসগুলি পপ করতে এবং "ব্যাক আপ" রাখতে পারেন। তারপরে সেই জায়গা থেকে আবার "এগিয়ে" যাওয়ার চেষ্টা করুন।

হ্যাক: আপনি যদি এসকিএল সার্ভার ২০০৮ ব্যবহার করেন তবে কিছু নতুন "হায়ারার্কি" রয়েছে যা আপনি খুব শীঘ্রই সমাধান করতে ব্যবহার করতে পারেন যদি আপনি কোনও গাছের মধ্যে আপনার ডেটা গঠন করেন।


3

পিছনের প্রান্তগুলি সহ ডিএফএস-ভিত্তিক রূপগুলি প্রকৃতপক্ষে চক্রটি খুঁজে পেতে পারে তবে অনেক ক্ষেত্রে এটি ন্যূনতম হবে না চক্র নয়। সাধারণভাবে ডিএফএস আপনাকে পতাকা দেয় যে একটি চক্র রয়েছে তবে এটি চক্রটি সন্ধান করার পক্ষে যথেষ্ট ভাল নয়। উদাহরণস্বরূপ, 5 টি পৃথক চক্র দুটি প্রান্ত ভাগ করে নেওয়ার কল্পনা করুন। স্রেফ ডিএফএস (ব্যাকট্র্যাকিং ভেরিয়েন্ট সহ) ব্যবহার করে চক্র সনাক্ত করার কোনও সহজ উপায় নেই।

জনসনের অ্যালগরিদম প্রকৃতপক্ষে সমস্ত অনন্য সাধারণ চক্র দেয় এবং এতে সময় এবং স্থানের জটিলতা রয়েছে।

তবে আপনি যদি কেবলমাত্র ন্যূনতম চক্রগুলি খুঁজতে চান (এর অর্থ যে কোনও চূড়ান্ত মধ্য দিয়ে আরও একটি চক্র থাকতে পারে এবং আমরা ন্যূনতমগুলি সন্ধান করতে আগ্রহী) এবং আপনার গ্রাফটি খুব বড় নয়, আপনি নীচের সহজ পদ্ধতিটি ব্যবহার করার চেষ্টা করতে পারেন। এটি জনসনের তুলনায় খুব সহজ তবে ধীর।

সুতরাং, ন্যূনতম চক্রটি সন্ধান করার একেবারে সহজ উপায় হ'ল সংলগ্ন ম্যাট্রিক্স ব্যবহার করে সমস্ত উল্লম্বের মধ্যে ন্যূনতম পাথগুলি খুঁজে পেতে ফ্লয়েডের অ্যালগরিদম ব্যবহার করা। এই অ্যালগরিদম জনসনের মতো সর্বোত্তম কাছাকাছি কোথাও নেই, তবে এটি এত সহজ এবং এর অভ্যন্তরীণ লুপটি এতটা শক্ত যে ছোট গ্রাফের জন্য (<= 50-100 নোড) এটি ব্যবহার করা একেবারেই বুদ্ধিমান। সময়ের জটিলতা হ'ল হে (এন ^ 3), স্পেস জটিলতা হে (এন ^ 2) আপনি প্যারেন্ট ট্র্যাকিং ব্যবহার করেন এবং যদি না করেন তবে হে (1)। প্রথমে একটি চক্র থাকলে প্রশ্নের উত্তর সন্ধান করি। অ্যালগরিদম মৃত-সহজ। নীচে স্কালায় স্নিপেট রয়েছে।

  val NO_EDGE = Integer.MAX_VALUE / 2

  def shortestPath(weights: Array[Array[Int]]) = {
    for (k <- weights.indices;
         i <- weights.indices;
         j <- weights.indices) {
      val throughK = weights(i)(k) + weights(k)(j)
      if (throughK < weights(i)(j)) {
        weights(i)(j) = throughK
      }
    }
  }

মূলত এই অ্যালগরিদমটি ভারী প্রান্তের গ্রাফটিতে সমস্ত জোড় নোডের মধ্যে সংক্ষিপ্ততম পাথগুলি খুঁজে পেতে (তাই ওজন যুক্তি) পরিচালনা করে। এটি সঠিকভাবে কাজ করার জন্য আপনাকে নোডের মধ্যে নির্দেশিত প্রান্ত বা অন্যথায় NO_EDGE থাকলে 1 টি সরবরাহ করতে হবে। অ্যালগরিদম কার্যকর করার পরে, আপনি মূল তির্যকটি পরীক্ষা করতে পারেন, যদি মানগুলি কম থাকে তবে NO_EDGE এই নোডের চেয়ে সমান দৈর্ঘ্যের চক্রে অংশ নেয়। একই চক্রের প্রতিটি অন্যান্য নোডের সমান মান হবে (মূল তিরুঙ্গে)।

চক্রটি নিজেই পুনর্গঠন করার জন্য আমাদের প্যারেন্ট ট্র্যাকিংয়ের সাথে অ্যালগরিদমের কিছুটা পরিবর্তিত সংস্করণ ব্যবহার করা দরকার।

  def shortestPath(weights: Array[Array[Int]], parents: Array[Array[Int]]) = {
    for (k <- weights.indices;
         i <- weights.indices;
         j <- weights.indices) {
      val throughK = weights(i)(k) + weights(k)(j)
      if (throughK < weights(i)(j)) {
        parents(i)(j) = k
        weights(i)(j) = throughK
      }
    }
  }

প্রথমদিকে পিতামাতার ম্যাট্রিক্সের প্রান্ত সেলটিতে উত্সের শীর্ষস্থানীয় সূচক থাকা উচিত যদি অন্যদিকে এবং -1 এর মধ্যে একটি প্রান্ত থাকে। ফাংশন ফিরে আসার পরে, প্রতিটি প্রান্তের জন্য আপনার সবচেয়ে সংক্ষিপ্ত পথ গাছের প্যারেন্ট নোডের রেফারেন্স থাকবে। এবং তারপরে প্রকৃত চক্রগুলি পুনরুদ্ধার করা সহজ।

সব মিলিয়ে সমস্ত ন্যূনতম চক্র সন্ধান করার জন্য আমাদের নীচের প্রোগ্রাম রয়েছে

  val NO_EDGE = Integer.MAX_VALUE / 2;

  def shortestPathWithParentTracking(
         weights: Array[Array[Int]],
         parents: Array[Array[Int]]) = {
    for (k <- weights.indices;
         i <- weights.indices;
         j <- weights.indices) {
      val throughK = weights(i)(k) + weights(k)(j)
      if (throughK < weights(i)(j)) {
        parents(i)(j) = parents(i)(k)
        weights(i)(j) = throughK
      }
    }
  }

  def recoverCycles(
         cycleNodes: Seq[Int], 
         parents: Array[Array[Int]]): Set[Seq[Int]] = {
    val res = new mutable.HashSet[Seq[Int]]()
    for (node <- cycleNodes) {
      var cycle = new mutable.ArrayBuffer[Int]()
      cycle += node
      var other = parents(node)(node)
      do {
        cycle += other
        other = parents(other)(node)
      } while(other != node)
      res += cycle.sorted
    }
    res.toSet
  }

এবং ফলাফলটি পরীক্ষা করার জন্য একটি ছোট্ট প্রধান পদ্ধতি

  def main(args: Array[String]): Unit = {
    val n = 3
    val weights = Array(Array(NO_EDGE, 1, NO_EDGE), Array(NO_EDGE, NO_EDGE, 1), Array(1, NO_EDGE, NO_EDGE))
    val parents = Array(Array(-1, 1, -1), Array(-1, -1, 2), Array(0, -1, -1))
    shortestPathWithParentTracking(weights, parents)
    val cycleNodes = parents.indices.filter(i => parents(i)(i) < NO_EDGE)
    val cycles: Set[Seq[Int]] = recoverCycles(cycleNodes, parents)
    println("The following minimal cycle found:")
    cycles.foreach(c => println(c.mkString))
    println(s"Total: ${cycles.size} cycle found")
  }

এবং আউটপুট হয়

The following minimal cycle found:
012
Total: 1 cycle found

2

পুনঃনির্দেশিত গ্রাফের ক্ষেত্রে, সম্প্রতি প্রকাশিত একটি কাগজ ( অনির্দেশিত গ্রাফগুলিতে চক্র এবং স্ট-পাথের অনুকূল তালিকা ) একটি আশ্রয়হীনভাবে অনুকূল সমাধান সরবরাহ করে। আপনি এটি এখানে http://arxiv.org/abs/1205.2766 পড়তে পারেন বা এখানে http://dl.acm.org/citation.cfm?id=2627951 আমি জানি এটি আপনার প্রশ্নের উত্তর দেয় না, তবে শিরোনামের পরে আপনার প্রশ্নে দিক নির্দেশনা উল্লেখ করা হয়নি, এটি Google অনুসন্ধানের জন্য এখনও কার্যকর হতে পারে


1

নোড এক্স থেকে শুরু করুন এবং সমস্ত শিশু নোডের জন্য পরীক্ষা করুন (পুনঃনির্দেশিত হলে পিতামাতার এবং শিশু নোডগুলি সমান)। এই শিশু নোডগুলিকে এক্সের সন্তান হিসাবে চিহ্নিত করুন such এ জাতীয় যে কোনও শিশু নোড থেকে এটি এ, এক্স 'এর সন্তান হওয়ার চিহ্ন চিহ্নিত করুন, যেখানে এক্স' কে 2 ধাপ দূরে চিহ্নিত করা হয়েছে))। যদি আপনি পরে এক্সকে আঘাত করেন এবং এটিকে X '' এর শিশু হিসাবে চিহ্নিত করেন, তার অর্থ X একটি 3 নোড চক্রের মধ্যে রয়েছে। এর পিতামাতাকে ব্যাকট্র্যাকিং করা সহজ (যেমনটি, অ্যালগরিদমের কোনও সমর্থন নেই তাই আপনি যে কোনও পিতামাতার এক্স 'রয়েছে তা খুঁজে পেতে পারেন)।

দ্রষ্টব্য: যদি গ্রাফটি পুনঃনির্দেশিত হয় বা কোনও দ্বিদ্বিদী প্রান্তগুলি থাকে তবে এই অ্যালগরিদম আরও জটিল হয়ে যায়, ধরে নিয়ে আপনি একই চক্রের জন্য দু'বার একই প্রান্তটি অতিক্রম করতে চান না।


1

আপনি যা চান তা যদি গ্রাফের সমস্ত প্রাথমিক সার্কিটগুলি সন্ধান করতে হয় তবে আপনি ১৯AME০ সাল থেকে একটি কাগজে পাওয়া যায় জেমস সি টিয়ার্নান দ্বারা ইসি অ্যালগরিদম ব্যবহার করতে পারেন।

খুব আসল ইসি অ্যালগরিদম হিসাবে আমি পিএইচপি এটি বাস্তবায়ন করতে পরিচালিত (আশা কোন ভুল হয় নিচে দেখানো)। এটি যদি থাকে তবে এটি লুপগুলিও সন্ধান করতে পারে। এই বাস্তবায়নের সার্কিটগুলি (যেটি মূল ক্লোন করার চেষ্টা করে) হ'ল শূন্য উপাদান। শূন্য এখানে অস্তিত্ব জন্য (আমরা এটি জানি নাল)।

এগুলি ছাড়াও নীচে অন্য বাস্তবায়ন অনুসরণ করে যা অ্যালগোরিদমকে আরও স্বতন্ত্রতা দেয়, এর অর্থ নোডগুলি কোথাও থেকে এমনকি নেতিবাচক সংখ্যাগুলি থেকে শুরু করতে পারে, যেমন -4, -3, -2, .. ইত্যাদি from

উভয় ক্ষেত্রে নোডগুলি ক্রমযুক্ত হওয়া প্রয়োজন।

আপনার মূল কাগজ জেমস সি। টিয়ারান প্রাথমিক এলার্জি সার্কিট অ্যালগরিদম অধ্যয়ন করতে হবে

<?php
echo  "<pre><br><br>";

$G = array(
        1=>array(1,2,3),
        2=>array(1,2,3),
        3=>array(1,2,3)
);


define('N',key(array_slice($G, -1, 1, true)));
$P = array(1=>0,2=>0,3=>0,4=>0,5=>0);
$H = array(1=>$P, 2=>$P, 3=>$P, 4=>$P, 5=>$P );
$k = 1;
$P[$k] = key($G);
$Circ = array();


#[Path Extension]
EC2_Path_Extension:
foreach($G[$P[$k]] as $j => $child ){
    if( $child>$P[1] and in_array($child, $P)===false and in_array($child, $H[$P[$k]])===false ){
    $k++;
    $P[$k] = $child;
    goto EC2_Path_Extension;
}   }

#[EC3 Circuit Confirmation]
if( in_array($P[1], $G[$P[$k]])===true ){//if PATH[1] is not child of PATH[current] then don't have a cycle
    $Circ[] = $P;
}

#[EC4 Vertex Closure]
if($k===1){
    goto EC5_Advance_Initial_Vertex;
}
//afou den ksana theoreitai einai asfales na svisoume
for( $m=1; $m<=N; $m++){//H[P[k], m] <- O, m = 1, 2, . . . , N
    if( $H[$P[$k-1]][$m]===0 ){
        $H[$P[$k-1]][$m]=$P[$k];
        break(1);
    }
}
for( $m=1; $m<=N; $m++ ){//H[P[k], m] <- O, m = 1, 2, . . . , N
    $H[$P[$k]][$m]=0;
}
$P[$k]=0;
$k--;
goto EC2_Path_Extension;

#[EC5 Advance Initial Vertex]
EC5_Advance_Initial_Vertex:
if($P[1] === N){
    goto EC6_Terminate;
}
$P[1]++;
$k=1;
$H=array(
        1=>array(1=>0,2=>0,3=>0,4=>0,5=>0),
        2=>array(1=>0,2=>0,3=>0,4=>0,5=>0),
        3=>array(1=>0,2=>0,3=>0,4=>0,5=>0),
        4=>array(1=>0,2=>0,3=>0,4=>0,5=>0),
        5=>array(1=>0,2=>0,3=>0,4=>0,5=>0)
);
goto EC2_Path_Extension;

#[EC5 Advance Initial Vertex]
EC6_Terminate:
print_r($Circ);
?>

তারপরে এটি অন্য বাস্তবায়ন, গ্রাফের চেয়ে আরও স্বতন্ত্র, গোটো এবং অ্যারের মান ব্যতীত, পরিবর্তে এটি অ্যারে কী ব্যবহার করে, পথ, গ্রাফ এবং সার্কিটগুলি অ্যারে কী হিসাবে সংরক্ষণ করা হয় (যদি আপনি চান তবে অ্যারের মানগুলি ব্যবহার করুন, কেবল প্রয়োজনীয় পরিবর্তন করুন লাইন)। উদাহরণ স্বরূপ দেখানোর জন্য গ্রাফ -4 থেকে শুরু হয়।

<?php

$G = array(
        -4=>array(-4=>true,-3=>true,-2=>true),
        -3=>array(-4=>true,-3=>true,-2=>true),
        -2=>array(-4=>true,-3=>true,-2=>true)
);


$C = array();


EC($G,$C);
echo "<pre>";
print_r($C);
function EC($G, &$C){

    $CNST_not_closed =  false;                          // this flag indicates no closure
    $CNST_closed        = true;                         // this flag indicates closure
    // define the state where there is no closures for some node
    $tmp_first_node  =  key($G);                        // first node = first key
    $tmp_last_node  =   $tmp_first_node-1+count($G);    // last node  = last  key
    $CNST_closure_reset = array();
    for($k=$tmp_first_node; $k<=$tmp_last_node; $k++){
        $CNST_closure_reset[$k] = $CNST_not_closed;
    }
    // define the state where there is no closure for all nodes
    for($k=$tmp_first_node; $k<=$tmp_last_node; $k++){
        $H[$k] = $CNST_closure_reset;   // Key in the closure arrays represent nodes
    }
    unset($tmp_first_node);
    unset($tmp_last_node);


    # Start algorithm
    foreach($G as $init_node => $children){#[Jump to initial node set]
        #[Initial Node Set]
        $P = array();                   // declare at starup, remove the old $init_node from path on loop
        $P[$init_node]=true;            // the first key in P is always the new initial node
        $k=$init_node;                  // update the current node
                                        // On loop H[old_init_node] is not cleared cause is never checked again
        do{#Path 1,3,7,4 jump here to extend father 7
            do{#Path from 1,3,8,5 became 2,4,8,5,6 jump here to extend child 6
                $new_expansion = false;
                foreach( $G[$k] as $child => $foo ){#Consider each child of 7 or 6
                    if( $child>$init_node and isset($P[$child])===false and $H[$k][$child]===$CNST_not_closed ){
                        $P[$child]=true;    // add this child to the path
                        $k = $child;        // update the current node
                        $new_expansion=true;// set the flag for expanding the child of k
                        break(1);           // we are done, one child at a time
            }   }   }while(($new_expansion===true));// Do while a new child has been added to the path

            # If the first node is child of the last we have a circuit
            if( isset($G[$k][$init_node])===true ){
                $C[] = $P;  // Leaving this out of closure will catch loops to
            }

            # Closure
            if($k>$init_node){                  //if k>init_node then alwaya count(P)>1, so proceed to closure
                $new_expansion=true;            // $new_expansion is never true, set true to expand father of k
                unset($P[$k]);                  // remove k from path
                end($P); $k_father = key($P);   // get father of k
                $H[$k_father][$k]=$CNST_closed; // mark k as closed
                $H[$k] = $CNST_closure_reset;   // reset k closure
                $k = $k_father;                 // update k
        }   } while($new_expansion===true);//if we don't wnter the if block m has the old k$k_father_old = $k;
        // Advance Initial Vertex Context
    }//foreach initial


}//function

?>

আমি ইসিকে বিশ্লেষণ করে নথিভুক্ত করেছি তবে দুর্ভাগ্যক্রমে ডকুমেন্টেশনটি গ্রীক ভাষায় রয়েছে।


1

একটি ড্যাজে সমস্ত চক্র সন্ধানের জন্য দুটি পদক্ষেপ (অ্যালগোরিদম) জড়িত।

প্রথম পদক্ষেপটি হ'ল দৃjan়ভাবে সংযুক্ত উপাদানগুলির সেট খুঁজতে টার্জনের অ্যালগরিদম ব্যবহার করা।

  1. যেকোন স্বেচ্ছাসেবী প্রান্ত থেকে শুরু করুন।
  2. ডিটিএফসটি সেই শীর্ষবিন্দু থেকে। প্রতিটি নোড এক্সের জন্য, দুটি নম্বর রাখুন, ডিএফএস_ইন্ডেক্স [এক্স] এবং ডিএফএস_লোভাল [এক্স]। যখন নোডটি পরিদর্শন করা হয় তখন ডিএফএস_ইন্ডেক্স [এক্স] সঞ্চয় করে, যখন ডিএফএস_লোভাল [এক্স] = মিনিট (ডিএফএস_লো [কে]) যেখানে k সমস্ত ডি xf বাচ্চা যা ডিফএস-স্প্যানিং গাছের এক্স এর সরাসরি পিতামাতার নয়।
  3. একই ডিএফএস_লোভাল [এক্স] সহ সমস্ত নোড একই দৃ strongly়ভাবে সংযুক্ত উপাদানগুলিতে।

দ্বিতীয় পদক্ষেপটি সংযুক্ত উপাদানগুলির মধ্যে চক্র (পাথ) সন্ধান করা। আমার পরামর্শ হায়ারহোলজারের অ্যালগরিদমের একটি পরিবর্তিত সংস্করণ ব্যবহার করা।

ধারণাটি হ'ল:

  1. যেকোন প্রারম্ভিক ভার্টেক্স ভি বেছে নিন এবং আপনি ভিটিতে ফিরে না আসা পর্যন্ত ver শীর্ষটি থেকে প্রান্তের একটি ট্রেইল অনুসরণ করুন v v ছাড়া অন্য কোনও শীর্ষবিন্দুতে আটকা পড়া সম্ভব নয়, কারণ সমস্ত উল্লম্বের সমান ডিগ্রি নিশ্চিত করে যে, যখন ট্রেইল অন্যটিতে প্রবেশ করবে ভার্টেক্স ডাব্লু অবশ্যই একটি অব্যবহৃত প্রান্ত থাকা উচিত ডাব্লু। এইভাবে গঠিত ট্যুরটি একটি বদ্ধ সফর, তবে প্রাথমিক গ্রাফের সমস্ত শীর্ষে এবং প্রান্তটি coverাকতে পারে না।
  2. যতক্ষণ না কোনও ভার্টেক্স ভি বিদ্যমান রয়েছে যা বর্তমান ট্যুরের সাথে সম্পর্কিত তবে এর সাথে সংলগ্ন প্রান্তগুলি ট্যুরের অংশ নয়, ভি থেকে অন্য ট্রেল শুরু করুন, অবিরত প্রান্তগুলি অনুসরণ করে আপনি ভিতে ফিরে না আসা পর্যন্ত, এবং এই পথে গঠিত ট্যুরে যোগ দিন আগের ভ্রমণ

এখানে একটি পরীক্ষার কেস সহ জাভা প্রয়োগের লিঙ্কটি রয়েছে:

http://stones333.blogspot.com/2013/12/find-cycles-in-directed-graph-dag.html


16
কীভাবে একটি চক্র একটি ডিএজি (নির্দেশিত অ্যাসাইক্লিক গ্রাফ) এ থাকতে পারে?
sky_coder123

এটি সমস্ত চক্রটি খুঁজে পায় না।
বিশ্ব রত্না

0

প্রশ্নটি নির্দেশিত গ্রাফগুলিতে চক্র অপসারণ সম্পর্কে ছিল, তবে এই দস্তাবেজটি পুনঃনির্দেশিতগুলির উপর।
izilotti

0

আমি নিম্নলিখিত অ্যালগরিদমকে হোঁচট খেয়েছি যা জনসনের অ্যালগরিদমের চেয়ে কমপক্ষে কার্যকর বলে মনে হচ্ছে (কমপক্ষে আরও বড় গ্রাফের জন্য)। টারজানের অ্যালগরিদমের তুলনায় আমি এর অভিনয় সম্পর্কে নিশ্চিত নই।
অতিরিক্তভাবে, আমি এটিকে এখনও কেবল ত্রিভুজগুলির জন্য পরীক্ষা করে দেখেছি। আগ্রহী হলে দয়া করে নরিশিগ চিবা এবং টাকানো নিশিজেকি ( http://dx.doi.org/10.1137/0214017 ) "অর্বোরিসিটি এবং সাবগ্রাফার তালিকাভুক্তকরণ অ্যালগরিদম" দেখুন


0

জাভাস্ক্রিপ্ট সমাধান বিচ্ছিন্নভাবে লিঙ্কযুক্ত তালিকা ব্যবহার করে। দ্রুত রান সময়ের জন্য সেট অরণ্যগুলিকে ছত্রভঙ্গ করতে আপগ্রেড করা যেতে পারে।

var input = '5\nYYNNN\nYYYNN\nNYYNN\nNNNYN\nNNNNY'
console.log(input);
//above solution should be 3 because the components are
//{0,1,2}, because {0,1} and {1,2} therefore {0,1,2}
//{3}
//{4}

//MIT license, authored by Ling Qing Meng

//'4\nYYNN\nYYYN\nNYYN\nNNNY'

//Read Input, preformatting
var reformat = input.split(/\n/);
var N = reformat[0];
var adjMatrix = [];
for (var i = 1; i < reformat.length; i++) {
    adjMatrix.push(reformat[i]);
}

//for (each person x from 1 to N) CREATE-SET(x)
var sets = [];
for (var i = 0; i < N; i++) {
    var s = new LinkedList();
    s.add(i);
    sets.push(s);
}

//populate friend potentials using combinatorics, then filters
var people =  [];
var friends = [];
for (var i = 0; i < N; i++) {
    people.push(i);
}
var potentialFriends = k_combinations(people,2);
for (var i = 0; i < potentialFriends.length; i++){
    if (isFriend(adjMatrix,potentialFriends[i]) === 'Y'){
        friends.push(potentialFriends[i]);
    }
}


//for (each pair of friends (x y) ) if (FIND-SET(x) != FIND-SET(y)) MERGE-SETS(x, y)
for (var i = 0; i < friends.length; i++) {
    var x = friends[i][0];
    var y = friends[i][1];
    if (FindSet(x) != FindSet(y)) {
        sets.push(MergeSet(x,y));
    }
}


for (var i = 0; i < sets.length; i++) {
    //sets[i].traverse();
}
console.log('How many distinct connected components?',sets.length);



//Linked List data structures neccesary for above to work
function Node(){
    this.data = null;
    this.next = null;
}

function LinkedList(){
    this.head = null;
    this.tail = null;
    this.size = 0;

    // Add node to the end
    this.add = function(data){
        var node = new Node();
        node.data = data;
        if (this.head == null){
            this.head = node;
            this.tail = node;
        } else {
            this.tail.next = node;
            this.tail = node;
        }
        this.size++;
    };


    this.contains = function(data) {
        if (this.head.data === data) 
            return this;
        var next = this.head.next;
        while (next !== null) {
            if (next.data === data) {
                return this;
            }
            next = next.next;
        }
        return null;
    };

    this.traverse = function() {
        var current = this.head;
        var toPrint = '';
        while (current !== null) {
            //callback.call(this, current); put callback as an argument to top function
            toPrint += current.data.toString() + ' ';
            current = current.next; 
        }
        console.log('list data: ',toPrint);
    }

    this.merge = function(list) {
        var current = this.head;
        var next = current.next;
        while (next !== null) {
            current = next;
            next = next.next;
        }
        current.next = list.head;
        this.size += list.size;
        return this;
    };

    this.reverse = function() {
      if (this.head == null) 
        return;
      if (this.head.next == null) 
        return;

      var currentNode = this.head;
      var nextNode = this.head.next;
      var prevNode = this.head;
      this.head.next = null;
      while (nextNode != null) {
        currentNode = nextNode;
        nextNode = currentNode.next;
        currentNode.next = prevNode;
        prevNode = currentNode;
      }
      this.head = currentNode;
      return this;
    }


}


/**
 * GENERAL HELPER FUNCTIONS
 */

function FindSet(x) {
    for (var i = 0; i < sets.length; i++){
        if (sets[i].contains(x) != null) {
            return sets[i].contains(x);
        }
    }
    return null;
}

function MergeSet(x,y) {
    var listA,listB;
    for (var i = 0; i < sets.length; i++){
        if (sets[i].contains(x) != null) {
            listA = sets[i].contains(x);
            sets.splice(i,1);
        }
    }
    for (var i = 0; i < sets.length; i++) {
        if (sets[i].contains(y) != null) {
            listB = sets[i].contains(y);
            sets.splice(i,1);
        }
    }
    var res = MergeLists(listA,listB);
    return res;

}


function MergeLists(listA, listB) {
    var listC = new LinkedList();
    listA.merge(listB);
    listC = listA;
    return listC;
}

//access matrix by i,j -> returns 'Y' or 'N'
function isFriend(matrix, pair){
    return matrix[pair[0]].charAt(pair[1]);
}

function k_combinations(set, k) {
    var i, j, combs, head, tailcombs;
    if (k > set.length || k <= 0) {
        return [];
    }
    if (k == set.length) {
        return [set];
    }
    if (k == 1) {
        combs = [];
        for (i = 0; i < set.length; i++) {
            combs.push([set[i]]);
        }
        return combs;
    }
    // Assert {1 < k < set.length}
    combs = [];
    for (i = 0; i < set.length - k + 1; i++) {
        head = set.slice(i, i+1);
        tailcombs = k_combinations(set.slice(i + 1), k - 1);
        for (j = 0; j < tailcombs.length; j++) {
            combs.push(head.concat(tailcombs[j]));
        }
    }
    return combs;
}

0

প্রারম্ভ নোড গুলি থেকে ডিএফএস, ট্র্যাভারসাল চলাকালীন ডিএফএস পাথের উপর নজর রাখুন, এবং যদি আপনি নোড ভি থেকে স এর পথে কোনও প্রান্ত খুঁজে পান তবে পাথটি রেকর্ড করুন। (v, s) হ'ল ডিএফএস গাছের পিছনের দিক এবং এটি একটি চক্রকে বোঝায় s


ভাল, তবে ওপি এটি সন্ধান করছে না: সমস্ত চক্র সন্ধান করুন, সম্ভবত ন্যূনতম।
শান এল

0

পারমিটেশন চক্র সম্পর্কে আপনার প্রশ্ন সম্পর্কে , এখানে আরও পড়ুন: https://www.codechef.com/problems/PCYCLE

আপনি এই কোডটি চেষ্টা করতে পারেন (আকার এবং অঙ্ক সংখ্যা লিখুন):

# include<cstdio>
using namespace std;

int main()
{
    int n;
    scanf("%d",&n);

    int num[1000];
    int visited[1000]={0};
    int vindex[2000];
    for(int i=1;i<=n;i++)
        scanf("%d",&num[i]);

    int t_visited=0;
    int cycles=0;
    int start=0, index;

    while(t_visited < n)
    {
        for(int i=1;i<=n;i++)
        {
            if(visited[i]==0)
            {
                vindex[start]=i;
                visited[i]=1;
                t_visited++;
                index=start;
                break;
            }
        }
        while(true)
        {
            index++;
            vindex[index]=num[vindex[index-1]];

            if(vindex[index]==vindex[start])
                break;
            visited[vindex[index]]=1;
            t_visited++;
        }
        vindex[++index]=0;
        start=index+1;
        cycles++;
    }

    printf("%d\n",cycles,vindex[0]);

    for(int i=0;i<(n+2*cycles);i++)
    {
        if(vindex[i]==0)
            printf("\n");
        else
            printf("%d ",vindex[i]);
    }
}

0

দ্বিতীয় তলের উত্তরের সিউডো-কোডের জন্য ডিএফএস সি ++ সংস্করণ:

void findCircleUnit(int start, int v, bool* visited, vector<int>& path) {
    if(visited[v]) {
        if(v == start) {
            for(auto c : path)
                cout << c << " ";
            cout << endl;
            return;
        }
        else 
            return;
    }
    visited[v] = true;
    path.push_back(v);
    for(auto i : G[v])
        findCircleUnit(start, i, visited, path);
    visited[v] = false;
    path.pop_back();
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.